new keyword ichida nima bo'ladi?
new operatori bajaradigan 4 qadam — yangi obyekt, prototype bog'lash, this bilan chaqirish, return qiymatini tekshirish — va arrow function bilan ishlamasligi.
26-dars
new keyword ichida nima bo'ladi?
1. Yuzaki qarash — bitta qator, lekin 4 ta ish
function Person(name) {
this.name = name;
}
const p1 = new Person('Ali');
Bu bitta qator ko'rinadi, lekin ichkarida V8 4 ta aniq qadamni ketma-ket bajaradi. Keling har birini alohida ochamiz.
2. new operatori bajaradigan 4 qadam
// new Person('Ali') ICHKARIDA aynan shu bajariladi:
// QADAM 1: Yangi, bo'sh obyekt yaratiladi
const newObj = {};
// QADAM 2: Yangi obyektning [[Prototype]]'i Person.prototype'ga bog'lanadi
Object.setPrototypeOf(newObj, Person.prototype);
// yoki eski uslubda: newObj.__proto__ = Person.prototype;
// QADAM 3: Person funksiyasi chaqiriladi, this = newObj qilib bog'langan holda
const result = Person.call(newObj, 'Ali');
// QADAM 4: Agar Person biror OBYEKT qaytarsa — o'sha qaytariladi.
// Aks holda (undefined, primitiv qaytarsa) — newObj qaytariladi.
const finalResult = (typeof result === 'object' && result !== null) ? result : newObj;
Keling, har bir qadamni chuqurroq ko'ramiz.
QADAM 1 — Yangi obyekt yaratiladi (Heap'da)
const newObj = {};
V8 heap'da yangi, bo'sh obyekt yaratadi — hozircha Hidden Class C0 {} (bo'sh, hech qanday property yo'q).
HEAP:
newObj {} ← hali hech narsa yo'q, Hidden Class: C0
QADAM 2 — Prototype bog'lanadi
newObj.[[Prototype]] = Person.prototype;
Aynan shu qadamda p1.__proto__ === Person.prototype bo'lishi ta'minlanadi. Bu — Prototype Chainning boshlanish nuqtasi:
HEAP:
newObj {}
[[Prototype]] ──→ Person.prototype { greet, constructor }
Muhim: bu bog'lanish — Person funksiyasi ichidagi kod (this.name = name) ishga tushishidan oldin sodir bo'ladi. Ya'ni this — funksiya tanasi bajarilishidan avval allaqachon to'liq shakllangan, prototype'ga ulangan obyekt.
QADAM 3 — Funksiya this = yangi obyekt bilan chaqiriladi
Person.call(newObj, 'Ali');
Bu — call mexanizmi orqali ishlaydi! Person funksiyasi ichidagi this endi newObjga bog'langan. Funksiya tanasi bajariladi:
function Person(name) {
this.name = name; // this === newObj, shuning uchun: newObj.name = 'Ali'
}
Bu qatorda newObjga yangi property qo'shiladi — bu Transition Chainni ishga tushiradi:
newObj Hidden Class: C0 {} → C1 {name} (yangi Hidden Class'ga o'tdi)
HEAP:
newObj { name: 'Ali' }
[[Prototype]] ──→ Person.prototype { greet, constructor }
QADAM 4 — Return qiymati tekshiriladi (eng ko'p e'tibordan chetda qoladigan qism!)
Bu — eng kam odam biladigan, lekin juda muhim qoida:
function Person(name) {
this.name = name;
// return yozilmagan — avtomatik "return this" kabi ishlaydi
}
Agar constructor function hech narsa qaytarmasa (yoki undefined, yoki primitiv qiymat qaytarsa) — new operatori avtomatik ravishda thisni (ya'ni newObjni) qaytaradi.
function Person(name) {
this.name = name;
return 42; // PRIMITIV qiymat — E'TIBORGA OLINMAYDI!
}
const p1 = new Person('Ali');
console.log(p1.name); // 'Ali' — 42 emas, newObj qaytdi!
Lekin agar constructor OBYEKT qaytarsa — o'sha obyekt newObjning o'rniga qaytariladi:
function Person(name) {
this.name = name;
return { name: 'Boshqa obyekt', special: true }; // OBYEKT — bu qaytadi!
}
const p1 = new Person('Ali');
console.log(p1.name); // 'Boshqa obyekt' — newObj TASHLAB YUBORILDI!
console.log(p1.special); // true
console.log(p1 instanceof Person); // false! — chunki bu newObj emas
Bu qoida spesifikatsiyada aniq belgilangan: agar constructor'ning return qiymati typeof === 'object' (yoki funksiya) bo'lsa va null bo'lmasa — o'sha qiymat ishlatiladi, this (newObj) butunlay tashlab yuboriladi (garbage collector uni yig'ib oladi, chunki hech kim unga ishora qilmay qoladi).
3. To'liq V8 pseudocode — hammasi birga
function NEW(ConstructorFn, ...args) {
// 1. Yangi bo'sh obyekt
const newObj = {};
// 2. Prototype bog'lash
Object.setPrototypeOf(newObj, ConstructorFn.prototype);
// 3. Constructor'ni this=newObj bilan chaqirish
const result = ConstructorFn.apply(newObj, args);
// 4. Qaytariladigan qiymatni aniqlash
if (typeof result === 'object' && result !== null) {
return result; // obyekt qaytgan bo'lsa — o'shani beramiz
}
if (typeof result === 'function') {
return result; // funksiya ham "obyekt" hisoblanadi shu yerda
}
return newObj; // aks holda — yaratilgan obyektni qaytaramiz
}
// new Person('Ali') ekvivalenti:
const p1 = NEW(Person, 'Ali');
4. Nega bu tartib muhim — real xato misoli
function Config(options) {
this.options = options || {};
// Xato: dasturchi "agar options bo'sh bo'lsa, default obyekt qaytaray" deb o'ylagan
if (!options) {
return {}; // ❌ BU YANGI, BO'SH OBYEKT — Config'ga aloqasi yo'q!
}
}
const c1 = new Config();
console.log(c1 instanceof Config); // false! — kutilmagan natija
console.log(c1.options); // undefined! — chunki bu newObj emas, boshqa {}
Bu juda muhim tuzoq: constructor ichida hech qachon shartli ravishda obyekt return qilmang, aks holda new operatorining butun mo'ljalini (yangi, to'g'ri bog'langan instance yaratish) buzasiz.
5. Arrow function nega new bilan ishlamaydi?
const Person = (name) => {
this.name = name;
};
new Person('Ali'); // TypeError: Person is not a constructor
Arrow function larda .prototype umuman yo'q. new operatorining 2-qadami (newObj.[[Prototype]] = Fn.prototype) bajarilishi uchun Fn.prototype mavjud bo'lishi shart. Arrow function'da bu yo'q — shuning uchun V8 new chaqirilishini darhol, ishga tushmasdanoq rad etadi (TypeError).
Bundan tashqari, arrow function'ning o'z thisi yo'q (lexical this ishlatadi) — shuning uchun ham new orqali "yangi this bog'lash" tushunchasi arrow function uchun mantiqan mos emas.
6. Xulosa — 4 qadam, vizual
new Person('Ali')
│
▼
┌───────────────────────────────────────────┐
│ 1. newObj = {} │ ← bo'sh obyekt, Heap'da
├───────────────────────────────────────────┤
│ 2. newObj.[[Prototype]] = Person.prototype │ ← zanjirga ulanadi
├───────────────────────────────────────────┤
│ 3. Person.call(newObj, 'Ali') │ ← this=newObj, funksiya tanasi ishlaydi
│ → newObj.name = 'Ali' │
├───────────────────────────────────────────┤
│ 4. return qiymatini tekshirish: │
│ - obyekt qaytdimi? → o'shani ber │
│ - aks holda → newObj'ni ber │
└───────────────────────────────────────────┘
│
▼
p1 = newObj (odatda)
Bir gapda: new — bu spetsifikatsiyada qattiq belgilangan 4 qadamli protsedura: bo'sh obyekt yaratish → uni constructor'ning prototypeiga bog'lash → constructor'ni shu obyekt this qilib chaqirish → agar constructor obyekt qaytarsa o'shani, aks holda yaratilgan obyektni natija sifatida berish.