å¨ç¼ç¨ä¸ï¼ç»§æ¿æ¯æå°ç¹æ§ä»ç¶ä»£ä¼ éç»å代ï¼ä»¥ä¾¿æ°ä»£ç å¯ä»¥éç¨å¹¶åºäºç°æä»£ç çç¹æ§è¿è¡æå»ºãJavaScript 使ç¨å¯¹è±¡å®ç°ç»§æ¿ãæ¯ä¸ªå¯¹è±¡é½æä¸æ¡é¾æ¥å°å¦ä¸ä¸ªç§°ä½ååç对象çå
é¨é¾ã该åå对象æèªå·±çååï¼ä¾æ¤ç±»æ¨ï¼ç´å°å忝 null
çå¯¹è±¡ãæ ¹æ®å®ä¹ï¼null
没æååï¼å¹¶ä½ä¸ºè¿æ¡ååé¾ä¸æåçä¸ç¯ãå¨è¿è¡æ¶ä¿®æ¹ååé¾ç任使åãçè³æ¯æ¢æåå齿¯å¯è½çï¼æä»¥åéæåæ´¾è¿æ ·çæ¦å¿µå¨ JavaScript ä¸ä¸åå¨ã
å¯¹äºæåºäºç±»çè¯è¨ï¼å¦ Java æ C++ï¼ç»éªçå¼åè æ¥è¯´ï¼JavaScript æäºä»¤äººå°æââå ä¸ºå®æ¯å¨æç并䏿²¡æéæç±»åã尽管è¿ä¸ªå°æéå¸¸è¢«è®¤ä¸ºæ¯ JavaScript çå¼±ç¹ä¹ä¸ï¼ä½æ¯ååç»§æ¿æ¨¡åå®é 䏿¯ç±»å¼æ¨¡åæ´å¼ºå¤§ãä¾å¦ï¼å¨å忍¡åçåºç¡ä¸æå»ºç±»å¼æ¨¡åï¼å³ç±»çå®ç°æ¹å¼ï¼ç¸å½ç®åã
尽管类ç°å¨è¢«å¹¿æ³ä½¿ç¨å¹¶æä¸º JavaScript 䏿°çèå¼ï¼ä½æ¯ç±»å¹¶æ²¡æå¼å ¥æ°çç»§æ¿æ¨¡å¼ã尽管类æ½è±¡æäºå¤§é¨åçååæºå¶ï¼ä½æ¯çè§£ååçåºå±å·¥ä½æºå¶ä»ç¶ååæç¨ã
åºäºååé¾çç»§æ¿ ç»§æ¿å±æ§JavaScript 对象æ¯å¨æç屿§ï¼ç§°ä¸ºèªæå±æ§ï¼âå âãJavaScript 对象æä¸æ¡æååå对象çé¾ãå½è¯å¾è®¿é®å¯¹è±¡ç屿§æ¶ï¼ä¸ä» å¨è¯¥å¯¹è±¡ä¸æ¥æ¾å±æ§ï¼è¿ä¼å¨è¯¥å¯¹è±¡çåå䏿¥æ¾å±æ§ï¼ä»¥åååçååï¼ä¾æ¤ç±»æ¨ï¼ç´å°æ¾å°ä¸ä¸ªååå¹é ç屿§æå°è¾¾ååé¾çæ«å°¾ã
夿³¨ï¼ æ ¹æ® ECMAScript æ åï¼ç¬¦å· someObject.[[Prototype]]
ç¨äºæå® someObject
çååãä½¿ç¨ Object.getPrototypeOf()
å Object.setPrototypeOf()
彿°åå«è®¿é®åä¿®æ¹ [[Prototype]]
å
é¨ææ§½ãè¿ä¸ JavaScript 访é®å¨ __proto__
æ¯çä»·çï¼åè
æ¯éæ åçï¼ä½è®¸å¤ JavaScript 弿å®é
ä¸å®ç°äºå®ã为äºä¿æç®æ´åé¿å
å°æï¼å¨æä»¬ç表示æ³ä¸ï¼æä»¬ä¼é¿å
ä½¿ç¨ obj.__proto__
ï¼èæ¯ä½¿ç¨ obj.[[Prototype]]
ãå
¶å¯¹åºäº Object.getPrototypeOf(obj)
ã
ä¸åºå°å®ä¸å½æ°ç func.prototype
屿§å¼æ··ï¼åè
表æçæ¯æå®å½æ°ä½ä¸ºæé 彿°æ¶åå»ºçææå¯¹è±¡å®ä¾ç [[Prototype]]
ãæä»¬å°å¨åé¢çå°èä¸è®¨è®ºæé 彿°ç prototype
屿§ã
æå ç§å¯ä»¥æå®å¯¹è±¡ç [[Prototype]]
çæ¹æ³ï¼è¿äºæ¹æ³å°å¨åé¢çå°èä¸ååºãç°å¨ï¼æä»¬å°ä½¿ç¨ __proto__
è¯æ³è¿è¡è¯´æãå¼å¾æ³¨æçæ¯ï¼{ __proto__: ... }
è¯æ³ä¸ obj.__proto__
访é®å¨ä¸åï¼åè
æ¯æ å䏿ªè¢«å¼ç¨çã
å¨å { a: 1, b: 2, __proto__: c }
è¿æ ·ç对象åé¢éä¸ï¼å¼ c
ï¼å
¶å¿
须为 null
æå¦ä¸ä¸ªå¯¹è±¡ï¼å°åæåé¢éæè¡¨ç¤ºç对象ç [[Prototype]]
ï¼èå
¶ä»å a
å b
è¿æ ·çé®å°åæå¯¹è±¡çèªæå±æ§ãè¿ç§è¯æ³è¯»èµ·æ¥é常èªç¶ï¼å 为 [[Prototype]]
åªæ¯å¯¹è±¡çâå
é¨å±æ§âã
ä¸é¢æ¼ç¤ºå½å°è¯è®¿é®å±æ§æ¶ä¼åçä»ä¹ï¼
const o = {
a: 1,
b: 2,
// __proto__ è®¾ç½®äº [[Prototype]]ãå¨è¿éå®è¢«æå®ä¸ºå¦ä¸ä¸ªå¯¹è±¡åé¢éã
__proto__: {
b: 3,
c: 4,
},
};
// o.[[Prototype]] å
·æå±æ§ b å cã
// o.[[Prototype]].[[Prototype]] æ¯ Object.prototypeï¼æä»¬ä¼å¨ä¸æè§£éå
¶å«ä¹ï¼ã
// æåï¼o.[[Prototype]].[[Prototype]].[[Prototype]] æ¯ nullã
// è¿æ¯ååé¾çæ«å°¾ï¼
// å ä¸ºæ ¹æ®å®ä¹ï¼null 没æ [[Prototype]]ã
// å æ¤ï¼å®æ´çååé¾çèµ·æ¥åè¿æ ·ï¼
// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> Object.prototype ---> null
console.log(o.a); // 1
// o ä¸æèªæå±æ§âaâåï¼æï¼ä¸å
¶å¼ä¸º 1ã
console.log(o.b); // 2
// o ä¸æèªæå±æ§âbâåï¼æï¼ä¸å
¶å¼ä¸º 2ã
// åå乿âbâ屿§ï¼ä½å
¶æ²¡æè¢«è®¿é®ã
// è¿è¢«ç§°ä¸ºå±æ§é®è½ï¼Property Shadowingï¼
console.log(o.c); // 4
// o ä¸æèªæå±æ§âcâåï¼æ²¡æï¼æ£æ¥å
¶ååã
// o.[[Prototype]] ä¸æèªæå±æ§âcâåï¼æï¼å
¶å¼ä¸º 4ã
console.log(o.d); // undefined
// o ä¸æèªæå±æ§âdâåï¼æ²¡æï¼æ£æ¥å
¶ååã
// o.[[Prototype]] ä¸æèªæå±æ§âdâåï¼æ²¡æï¼æ£æ¥å
¶ååã
// o.[[Prototype]].[[Prototype]] æ¯ Object.prototype ä¸
// å
¶é»è®¤æ²¡æâdâ屿§ï¼æ£æ¥å
¶ååã
// o.[[Prototype]].[[Prototype]].[[Prototype]] 为 nullï¼åæ¢æç´¢ï¼
// æªæ¾å°è¯¥å±æ§ï¼è¿å undefinedã
ç»å¯¹è±¡è®¾ç½®å±æ§ä¼åå»ºèªæå±æ§ãè·åå设置è¡ä¸ºè§åçå¯ä¸ä¾å¤æ¯å½å®è¢« getter æ setter æ¦æªæ¶ã
åçï¼ä½ å¯ä»¥å建æ´é¿çååé¾ï¼å¹¶å¨ææçååé¾ä¸æ¥æ¾å±æ§ã
const o = {
a: 1,
b: 2,
// __proto__ è®¾ç½®äº [[Prototype]]ãå¨è¿éå®è¢«æå®ä¸ºå¦ä¸ä¸ªå¯¹è±¡åé¢éã
__proto__: {
b: 3,
c: 4,
__proto__: {
d: 5,
},
},
};
// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> { d: 5 } ---> Object.prototype ---> null
console.log(o.d); // 5
ç»§æ¿âæ¹æ³â
JavaScript ä¸å®ä¹âæ¹æ³âçå½¢å¼ååºäºç±»çè¯è¨å®ä¹æ¹æ³çå½¢å¼ä¸åãå¨ JavaScript ä¸ï¼å¯¹è±¡å¯ä»¥ä»¥å±æ§ç形弿·»å 彿°ãç»§æ¿ç彿°ä¸å ¶ä»å±æ§ä¸æ ·ï¼å æ¬å±æ§é®è½ï¼å¨è¿ç§æ åµä¸ï¼æ¯ä¸ç§æ¹æ³éåçå½¢å¼ï¼ã
彿§è¡ç»§æ¿ç彿°æ¶ï¼this
弿åç»§æ¿å¯¹è±¡ï¼è䏿¯å°è¯¥å½æ°ä½ä¸ºå
¶èªæå±æ§çåå对象ã
const parent = {
value: 2,
method() {
return this.value + 1;
},
};
console.log(parent.method()); // 3
// å½è°ç¨ parent.method æ¶ï¼âthisâæåäº parent
// child æ¯ä¸ä¸ªç»§æ¿äº parent ç对象
const child = {
__proto__: parent,
};
console.log(child.method()); // 3
// è°ç¨ child.method æ¶ï¼âthisâæåäº childã
// åå 为 child ç»§æ¿çæ¯ parent çæ¹æ³ï¼
// é¦å
å¨ child ä¸å¯»æ¾å±æ§âvalueâã
// ç¶èï¼å 为 child 没æå为âvalueâçèªæå±æ§ï¼
// è¯¥å±æ§ä¼å¨ [[Prototype]] ä¸è¢«æ¾å°ï¼å³ parent.valueã
child.value = 4; // å° child ä¸ç屿§âvalueâèµå¼ä¸º 4ã
// è¿ä¼é®è½ parent ä¸çâvalueâ屿§ã
// child 对象ç°å¨çèµ·æ¥æ¯è¿æ ·çï¼
// { value: 4, __proto__: { value: 2, method: [Function] } }
console.log(child.method()); // 5
// å 为 child ç°å¨æ¥æâvalueâ屿§ï¼âthis.valueâç°å¨è¡¨ç¤º child.value
æé 彿°
ååç强大ä¹å¤å¨äºï¼å¦æä¸ç»å±æ§åºè¯¥åºç°å¨æ¯ä¸ä¸ªå®ä¾ä¸ï¼é£æä»¬å°±å¯ä»¥å¤ç¨å®ä»¬ââå°¤å
¶æ¯å¯¹äºæ¹æ³ãå设æä»¬è¦å建å¤ä¸ªçåï¼å
¶ä¸æ¯ä¸ä¸ªçå齿¯ä¸ä¸ªå¯¹è±¡ï¼å
å«ä¸ä¸ªå¯ä»¥éè¿ getValue
彿°è®¿é®çå¼ãä¸ä¸ªç®åçå®ç°å¯è½æ¯ï¼
const boxes = [
{ value: 1, getValue() { return this.value; } },
{ value: 2, getValue() { return this.value; } },
{ value: 3, getValue() { return this.value; } },
];
è¿æ¯ä¸å¤å¥½çï¼å 为æ¯ä¸ä¸ªå®ä¾é½æèªå·±çï¼åç¸åäºæ
ç彿°å±æ§ï¼è¿æ¯åä½ä¸ä¸å¿
è¦çãç¸åï¼æä»¬å¯ä»¥å° getValue
ç§»å¨å°ææçåç [[Prototype]]
ä¸ï¼
const boxPrototype = {
getValue() {
return this.value;
},
};
const boxes = [
{ value: 1, __proto__: boxPrototype },
{ value: 2, __proto__: boxPrototype },
{ value: 3, __proto__: boxPrototype },
];
è¿æ ·ï¼ææçåç getValue
æ¹æ³é½ä¼å¼ç¨ç¸åç彿°ï¼éä½äºå
å使ç¨çã使¯ï¼ä¸ºæ¯ä¸ªå¯¹è±¡å建æå¨ç»å® __proto__
仿§é叏䏿¹ä¾¿ãè¿æ¶ï¼æä»¬å°±å¯ä»¥ä½¿ç¨æé 彿°ï¼å®ä¼èªå¨ä¸ºæ¯ä¸ªæé ç对象设置 [[Prototype]]
ãæé 彿°æ¯ä½¿ç¨ new
è°ç¨ç彿°ã
// æé 彿°
function Box(value) {
this.value = value;
}
// ä½¿ç¨ Box() æé 彿°åå»ºçææçåé½å°å
·æç屿§
Box.prototype.getValue = function () {
return this.value;
};
const boxes = [new Box(1), new Box(2), new Box(3)];
æä»¬è¯´ new Box(1)
æ¯éè¿ Box
æé 彿°å建çä¸ä¸ªå®ä¾ãBox.prototype
䏿们ä¹åå建ç boxPrototype
å¹¶æ 太大åºå«ââå®åªæ¯ä¸ä¸ªæ®éç对象ãéè¿æé 彿°åå»ºçæ¯ä¸ä¸ªå®ä¾é½ä¼èªå¨å°æé 彿°ç prototype
屿§ä½ä¸ºå
¶ [[Prototype]]
ãå³ï¼Object.getPrototypeOf(new Box()) === Box.prototype
ãConstructor.prototype
é»è®¤å
·æä¸ä¸ªèªæå±æ§ï¼constructor
ï¼å®å¼ç¨äºæé 彿°æ¬èº«ãå³ï¼Box.prototype.constructor === Box
ãè¿å
许æä»¬å¨ä»»ä½å®ä¾ä¸è®¿é®åå§æé 彿°ã
夿³¨ï¼ 妿æé 彿°è¿åéåå§å¼ï¼å该å¼å°æä¸º new
表达å¼çç»æãå¨è¿ç§æ
åµä¸ï¼å¯è½æ æ³æ£ç¡®ç»å® [[Prototype]]
ââä½å¨å®è·µä¸åºè¯¥å¾å°åçã
ç¨ç±»å°ä¸é¢çæé 彿°éå为ï¼
class Box {
constructor(value) {
this.value = value;
}
// å¨ Box.prototype ä¸åå»ºæ¹æ³
getValue() {
return this.value;
}
}
ç±»æ¯æé 彿°çè¯æ³ç³ï¼è¿æå³çä½ ä»ç¶å¯ä»¥ä¿®æ¹ Box.prototype
æ¥æ¹åææå®ä¾çè¡ä¸ºãç¶èï¼ç±äºç±»è¢«è®¾è®¡ä¸ºå¯¹åºå±ååæºå¶çæ½è±¡ï¼æä»¬å°å¨æ¬æç¨ä¸ä½¿ç¨æ´è½»é级çæé 彿°è¯æ³ï¼ä»¥å
åå±ç¤ºååçå·¥ä½åçã
å 为 Box.prototype
å¼ç¨çå¯¹è±¡åææå®ä¾ç [[Prototype]]
æ¯åä¸ä¸ªå¯¹è±¡ï¼æä»¥æä»¬å¯ä»¥éè¿æ¹å Box.prototype
æ¥æ¹åææå®ä¾çè¡ä¸ºã
function Box(value) {
this.value = value;
}
Box.prototype.getValue = function () {
return this.value;
};
const box = new Box(1);
// å¨å建å®ä¾åä¿®æ¹ Box.prototype
Box.prototype.getValue = function () {
return this.value + 1;
};
box.getValue(); // 2
æä¸ªæ¨è®ºæ¯ï¼éæ°èµå¼ Constructor.prototype
ï¼Constructor.prototype = ...
ï¼æ¯ä¸ä¸ªä¸å¥½ç主æï¼åå æä¸¤ç¹ï¼
[[Prototype]]
å¼ç¨ç对象ä¸éæ°èµå¼ä¹åå建çå®ä¾ç [[Prototype]]
å¼ç¨ç对象ç°å¨æ¯ä¸åçââæ¹åä¸ä¸ªç [[Prototype]]
ä¸åæ¹åå¦ä¸ä¸ªç [[Prototype]]
ãconstructor
屿§ï¼å¦åæ æ³åéè¿ instance.constructor
è¿½è¸ªå°æé 彿°ï¼è¿å¯è½ä¼ç ´åç¨æ·ææçè¡ä¸ºãä¸äºå
ç½®æä½ä¹ä¼è¯»å constructor
屿§ï¼å¦ææ²¡æè®¾ç½®ï¼å®ä»¬å¯è½æ æ³æé¢æå·¥ä½ãConstructor.prototype
ä»
卿é å®ä¾æ¶æç¨ãå®ä¸ Constructor.[[Prototype]]
æ å
³ï¼åè
æ¯æé 彿°çèªæååï¼å³ Function.prototype
ãä¹å°±æ¯è¯´ï¼Object.getPrototypeOf(Constructor) === Function.prototype
ã
JavaScript ä¸çä¸äºåé¢éè¯æ³ä¼å建éå¼è®¾ç½® [[Prototype]]
çå®ä¾ãä¾å¦ï¼
// 对象åé¢éï¼æ²¡æ `__proto__` é®ï¼èªå¨å° `Object.prototype` ä½ä¸ºå®ä»¬ç `[[Prototype]]`
const object = { a: 1 };
Object.getPrototypeOf(object) === Object.prototype; // true
// æ°ç»åé¢éèªå¨å° `Array.prototype` ä½ä¸ºå®ä»¬ç `[[Prototype]]`
const array = [1, 2, 3];
Object.getPrototypeOf(array) === Array.prototype; // true
// æ£å表达å¼åé¢éèªå¨å° `RegExp.prototype` ä½ä¸ºå®ä»¬ç `[[Prototype]]`
const regexp = /abc/;
Object.getPrototypeOf(regexp) === RegExp.prototype; // true
æä»¬å¯ä»¥å°å®ä»¬âè§£ç³ï¼de-sugarï¼â为æé 彿°å½¢å¼ã
const array = new Array(1, 2, 3);
const regexp = new RegExp("abc");
ä¾å¦ï¼å map()
è¿æ ·çâæ°ç»æ¹æ³âæ¯ä»
å¨ Array.prototype
ä¸å®ä¹çæ¹æ³ï¼èå®ä»¬åèªå¨å¨æææ°ç»å®ä¾ä¸å¯ç¨ï¼å°±æ¯å 为è¿ä¸ªåå ã
è¦åï¼ æä¸ä¸ªå¸¸è§çé误å®è·µï¼misfeatureï¼ï¼æ©å± Object.prototype
æå
¶å®å
ç½®ååãè¿ç§ä¸è¯ç¹æ§ä¾åæ¯ï¼å®ä¹ Array.prototype.myMethod = function () {...}
ï¼ç¶åå¨æææ°ç»å®ä¾ä¸ä½¿ç¨ myMethod
ã
è¿ç§é误å®è·µè¢«ç§°ä¸ºç´å修补ï¼monkey patchingï¼ã使ç¨ç´å修补åå¨ååå ¼å®¹çé£é©ï¼å ä¸ºå¦æè¯è¨å¨æªæ¥æ·»å äºæ¤æ¹æ³ä½å ·æä¸åçç¾åï¼ä½ ç代ç å°ä¼åºéãå®å·²ç»å¯¼è´äºç±»ä¼¼äº SmooshGate è¿æ ·çäºä»¶ï¼å¹¶ä¸å 为 JavaScript è´åäºâä¸ç ´å webâï¼æä»¥è¿å¯è½ä¼å¯¹è¯è¨çåå±é ææå¤§ç麻ç¦ã
æ©å±å
ç½®ååçå¯ä¸çç±æ¯ååç§»æ¤æ°ç JavaScript 弿çç¹æ§ï¼æ¯å¦ Array.prototype.forEach
ã
æè¶£çæ¯ï¼ç±äºåå²åå ï¼ä¸äºå
ç½®æé 彿°ç prototype
屿§æ¬èº«å°±æ¯å
¶èªèº«çå®ä¾ãä¾å¦ï¼Number.prototype
æ¯æ°å 0ï¼Array.prototype
æ¯ä¸ä¸ªç©ºæ°ç»ï¼RegExp.prototype
æ¯ /(?:)/
ã
Number.prototype + 1; // 1
Array.prototype.map((x) => x + 1); // []
String.prototype + "a"; // "a"
RegExp.prototype.source; // "(?:)"
Function.prototype(); // Function.prototype æ¬èº«å°±æ¯ä¸ä¸ªæ æä½å½æ°
ç¶èï¼å¯¹äºç¨æ·å®ä¹çæé 彿°ï¼ä»¥å Map
çç°ä»£çæé 彿°ï¼åå¹¶é妿¤ã
Map.prototype.get(1);
// Uncaught TypeError: get method called on incompatible Map.prototype
æå»ºæ´é¿çç»§æ¿é¾
Constructor.prototype
屿§å°æä¸ºæé 彿°å®ä¾ç [[Prototype]]
ï¼å
æ¬ Constructor.prototype
èªèº«ç [[Prototype]]
ãé»è®¤æ
åµä¸ï¼Constructor.prototype
æ¯ä¸ä¸ªæ®é对象ââå³ Object.getPrototypeOf(Constructor.prototype) === Object.prototype
ãå¯ä¸çä¾å¤æ¯ Object.prototype
æ¬èº«ï¼å
¶ [[Prototype]]
æ¯ null
ââå³ Object.getPrototypeOf(Object.prototype) === null
ãå æ¤ï¼ä¸ä¸ªå
¸åçæé 彿°å°æå»ºä»¥ä¸ååé¾ï¼
function Constructor() {}
const obj = new Constructor();
// obj ---> Constructor.prototype ---> Object.prototype ---> null
è¦æå»ºæ´é¿çååé¾ï¼æä»¬å¯ä»¥éè¿ Object.setPrototypeOf()
彿°è®¾ç½® Constructor.prototype
ç [[Prototype]]
ã
function Base() {}
function Derived() {}
// å° `Derived.prototype` ç `[[Prototype]]`
// 设置为 `Base.prototype`
Object.setPrototypeOf(Derived.prototype, Base.prototype);
const obj = new Derived();
// obj ---> Derived.prototype ---> Base.prototype ---> Object.prototype ---> null
å¨ç±»çæ¯è¯ä¸ï¼è¿çåäºä½¿ç¨ extends
è¯æ³ã
class Base {}
class Derived extends Base {}
const obj = new Derived();
// obj ---> Derived.prototype ---> Base.prototype ---> Object.prototype ---> null
ä½ å¯è½è¿ä¼çå°ä¸äºä½¿ç¨ Object.create()
æ¥æå»ºç»§æ¿é¾çæ§ä»£ç ãç¶èï¼å 为è¿ä¼éæ°ä¸º prototype
屿§èµå¼å¹¶å é¤ constructor
屿§ï¼æä»¥æ´å®¹æåºéï¼èä¸å¦ææé 彿°è¿æ²¡æå建任ä½å®ä¾ï¼æ§è½æåå¯è½å¹¶ä¸ææ¾ã
function Base() {}
function Derived() {}
// å° `Derived.prototype` éæ°èµå¼ä¸ºä¸ä¸ªæ°å¯¹è±¡ï¼
// å¹¶å° `Base.prototype` ä½ä¸ºæ°å¯¹è±¡ç `[[Prototype]]`
// 请ä¸è¦è¿æ ·åââä½¿ç¨ Object.setPrototypeOf æ¥ä¿®æ¹å®
Derived.prototype = Object.create(Base.prototype);
æ£æ¥ååï¼æ´æ·±å
¥çç ç©¶
让æä»¬æ¥ä»ç»ççå¹ååçäºä»ä¹ã
å¦ä¸æè¿°ï¼å¨ JavaScript ä¸ï¼å½æ°å¯ä»¥æ¥æå±æ§ãææå½æ°é½æä¸ä¸ªå为 prototype
çç¹æ®å±æ§ã请注æï¼ä¸é¢çä»£ç æ¯ç¬ç«çï¼åºäºä¸¥è°¨ï¼åè®¾é¡µé¢æ²¡æå
¶ä»ç JavaScript 代ç ï¼ã为è·å¾æä½³çå¦ä¹ ä½éªï¼å¼ºçå»ºè®®ä½ æå¼æ§å¶å°ï¼è¿å
¥âconsoleâæ ç¾é¡µï¼å¤å¶å¹¶ç²è´´ä»¥ä¸ JavaScript 代ç ï¼ç¶åæå车é®è¿è¡ãï¼å¤§å¤æ° web æµè§å¨çå¼åè
å·¥å
·ä¸é½å
嫿§å¶å°ã请åé
Firefox å¼åè
å·¥å
·ãChrome å¼åè
å·¥å
·å Edge å¼åè
å·¥å
·ï¼ä»¥äºè§£è¯¦æ
ãï¼
function doSomething() {}
console.log(doSomething.prototype);
// ä½ å¦ä½å£°æå½æ°å¹¶ä¸éè¦ï¼
// JavaScript ä¸ç彿°æ»æä¸ä¸ªé»è®¤ç
// åå屿§ââæä¸ä¸ªä¾å¤ï¼
// ç®å¤´å½æ°æ²¡æé»è®¤çåå屿§ï¼
const doSomethingFromArrowFunction = () => {};
console.log(doSomethingFromArrowFunction.prototype);
å¦ä¸æç¤ºï¼doSomething()
æä¸ä¸ªé»è®¤ç prototype
屿§ï¼æ£å¦æ§å¶å°æç¤ºï¼ãè¿è¡è¿æ®µä»£ç åï¼æ§å¶å°åºè¯¥æ¾ç¤ºä¸ä¸ªç±»ä¼¼äºä¸é¢ç对象ã
{ constructor: Æ doSomething(), [[Prototype]]: { constructor: Æ Object(), hasOwnProperty: Æ hasOwnProperty(), isPrototypeOf: Æ isPrototypeOf(), propertyIsEnumerable: Æ propertyIsEnumerable(), toLocaleString: Æ toLocaleString(), toString: Æ toString(), valueOf: Æ valueOf() } }
夿³¨ï¼ éµå¾ªè§èçæ¯è¯ï¼Chrome æ§å¶å°ä½¿ç¨ [[Prototype]]
表示对象çååï¼è Firefox ä½¿ç¨ <prototype>
ã为äºä¿æä¸è´æ§ï¼æä»¬å°ä½¿ç¨ [[Prototype]]
ã
æä»¬å¯ä»¥åä¸é¢è¿æ ·ï¼å doSomething()
çååæ·»å 屿§ã
function doSomething() {}
doSomething.prototype.foo = "bar";
console.log(doSomething.prototype);
å ¶ç»æä¸ºï¼
{ foo: "bar", constructor: Æ doSomething(), [[Prototype]]: { constructor: Æ Object(), hasOwnProperty: Æ hasOwnProperty(), isPrototypeOf: Æ isPrototypeOf(), propertyIsEnumerable: Æ propertyIsEnumerable(), toLocaleString: Æ toLocaleString(), toString: Æ toString(), valueOf: Æ valueOf() } }
æä»¬ç°å¨å¯ä»¥ä½¿ç¨ new
è¿ç®ç¬¦å建åºäºè¯¥ååç doSomething()
çå®ä¾ãè¦ä½¿ç¨ new è¿ç®ç¬¦ï¼åªéæ£å¸¸è°ç¨å½æ°ï¼åªæ¯è¦å¨åé¢å ä¸ new
ãä½¿ç¨ new
è¿ç®ç¬¦è°ç¨å½æ°ä¼è¿åè¯¥å½æ°çå®ä¾å¯¹è±¡ãç¶åå¯ä»¥å¨è¯¥å¯¹è±¡ä¸æ·»å 屿§ã
å°è¯ä»¥ä¸ä»£ç ï¼
function doSomething() {}
doSomething.prototype.foo = "bar"; // åååæ·»å ä¸ä¸ªå±æ§
const doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value"; // å对象添å ä¸ä¸ªå±æ§
console.log(doSomeInstancing);
è¿ä¼äº§ç类似äºä¸é¢çè¾åºï¼
{ prop: "some value", [[Prototype]]: { foo: "bar", constructor: Æ doSomething(), [[Prototype]]: { constructor: Æ Object(), hasOwnProperty: Æ hasOwnProperty(), isPrototypeOf: Æ isPrototypeOf(), propertyIsEnumerable: Æ propertyIsEnumerable(), toLocaleString: Æ toLocaleString(), toString: Æ toString(), valueOf: Æ valueOf() } } }
å¦ä¸æç¤ºï¼doSomeInstancing
ç [[Prototype]]
æ¯ doSomething.prototype
ã使¯ï¼è¿æ¯åä»ä¹çå¢ï¼å½ä½ è®¿é® doSomeInstancing
ç屿§æ¶ï¼è¿è¡æ¶é¦å
伿¥æ¾ doSomeInstancing
æ¯å¦æè¯¥å±æ§ã
妿 doSomeInstancing
没æè¯¥å±æ§ï¼é£ä¹è¿è¡æ¶ä¼å¨ doSomeInstancing.[[Prototype]]
ï¼ä¹å°±æ¯ doSomething.prototype
ï¼ä¸æ¥æ¾è¯¥å±æ§ã妿 doSomeInstancing.[[Prototype]]
æè¯¥å±æ§ï¼é£ä¹å°±ä¼ä½¿ç¨ doSomeInstancing.[[Prototype]]
ä¸çè¯¥å±æ§ã
å¦åï¼å¦æ doSomeInstancing.[[Prototype]]
没æè¯¥å±æ§ï¼é£ä¹å°±ä¼å¨ doSomeInstancing.[[Prototype]].[[Prototype]]
䏿¥æ¾è¯¥å±æ§ãé»è®¤æ
åµä¸ï¼ä»»ä½å½æ°ç prototype
屿§ç [[Prototype]]
齿¯ Object.prototype
ãå æ¤ä¼å¨ doSomeInstancing.[[Prototype]].[[Prototype]]
ï¼ä¹å°±æ¯ doSomething.prototype.[[Prototype]]
ï¼ä¹å°±æ¯ Object.prototype
ï¼ï¼ä¸æ¥æ¾è¯¥å±æ§ã
å¦æå¨ doSomeInstancing.[[Prototype]].[[Prototype]]
䏿²¡ææ¾å°è¯¥å±æ§ï¼é£ä¹å°±ä¼å¨ doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]]
䏿¥æ¾è¯¥å±æ§ã使¯ï¼è¿éæä¸ä¸ªé®é¢ï¼doSomeInstancing.[[Prototype]].[[Prototype]].[[Prototype]]
ä¸åå¨ï¼å 为 Object.prototype.[[Prototype]]
æ¯ null
ãç¶åï¼åªæå¨æ¥æ¾å®æ´ä¸ª [[Prototype]]
çååé¾ä¹åï¼è¿è¡æ¶æä¼æè¨è¯¥å±æ§ä¸åå¨ï¼å¹¶å¾åºè¯¥å±æ§çå¼ä¸º undefined
ã
让æä»¬å¨æ§å¶å°ä¸è¾å ¥æ´å¤ç代ç ï¼
function doSomething() {}
doSomething.prototype.foo = "bar";
const doSomeInstancing = new doSomething();
doSomeInstancing.prop = "some value";
console.log("doSomeInstancing.prop: ", doSomeInstancing.prop);
console.log("doSomeInstancing.foo: ", doSomeInstancing.foo);
console.log("doSomething.prop: ", doSomething.prop);
console.log("doSomething.foo: ", doSomething.foo);
console.log("doSomething.prototype.prop:", doSomething.prototype.prop);
console.log("doSomething.prototype.foo: ", doSomething.prototype.foo);
å ¶ç»æå¦ä¸ï¼
doSomeInstancing.prop: some value doSomeInstancing.foo: bar doSomething.prop: undefined doSomething.foo: undefined doSomething.prototype.prop: undefined doSomething.prototype.foo: bar使ç¨ä¸åçæ¹æ³æ¥åå»ºå¯¹è±¡åæ¹åååé¾
æä»¬ç¢°å°è¿å¾å¤åå»ºå¯¹è±¡åæ¹åå ¶ååé¾çæ¹æ³ãæä»¬å°ç³»ç»å°æ»ç»ä¸åçæ¹æ³ï¼å¹¶æ¯è¾æ¯ç§æ¹æ³çä¼ç¼ºç¹ã
使ç¨è¯æ³ç»æå建对象const o = { a: 1 };
// æ°å建ç对象 o 以 Object.prototype ä½ä¸ºå®ç [[Prototype]]
// Object.prototype 以 null ä½ä¸ºå®ç [[Prototype]]ã
// o ---> Object.prototype ---> null
const b = ["yo", "whadup", "?"];
// æ°ç»ç»§æ¿äº Array.prototypeï¼å
·æ indexOfãforEach çæ¹æ³ï¼
// ååé¾å¦ä¸æç¤ºï¼
// b ---> Array.prototype ---> Object.prototype ---> null
function f() {
return 2;
}
// 彿°ç»§æ¿äº Function.prototypeï¼å
·æ callãbind çæ¹æ³ï¼
// f ---> Function.prototype ---> Object.prototype ---> null
const p = { b: 2, __proto__: o };
// å¯ä»¥éè¿ __proto__ åé¢é屿§ï¼ä¸è¦å°å
¶ä¸ Object.prototype.__proto__ 访é®å¨å¼æ··ï¼å°æ°å建ç对象ç
// [[Prototype]] æåå¦ä¸ä¸ªå¯¹è±¡ã
// p ---> o ---> Object.prototype ---> null
å¨å¯¹è±¡åå§åå¨ä¸ä½¿ç¨ __proto__
鮿¶ï¼å° __proto__
鮿åé对象çå¼åªä¼è¢«å¿½ç¥ï¼èéæåºå¼å¸¸ãä¸ Object.prototype.__proto__
ç setter ç¸åï¼å¯¹è±¡åé¢éåå§åå¨ä¸ç __proto__
æ¯æ ååçã被ä¼åçï¼çè³æ¯ Object.create
æ´é«æãå¨å建对象æ¶å£°æé¢å¤çèªæå±æ§æ¯ Object.create
æ´ç¬¦åä¹ æ¯ã
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype.addVertex = function (v) {
this.vertices.push(v);
};
const g = new Graph();
// g æ¯ä¸ä¸ªå¸¦æèªæå±æ§âverticesâåâedgesâç对象ã
// 卿§è¡ new Graph() æ¶ï¼g.[[Prototype]] æ¯ Graph.prototype çå¼ã
æé 彿°ä»å¾æ©æç JavaScript 就已ç»åå¨äºãå æ¤ï¼å®çé度é常快ï¼é常æ åï¼å¹¶ä¸é常容æè¢« JIT ä¼åãç¶èï¼å®ä¹å¾é¾âæ£ç¡®å°â使ç¨ï¼å 为éè¿è¿ç§æ¹å¼æ·»å çæ¹æ³é»è®¤æ¯å¯æä¸¾çï¼è¿ä¸ç±»è¯æ³æå ç½®æ¹æ³çè¡ä¸ºä¸ä¸è´ãè¿è¡æ´é¿çç»§æ¿é¾ä¹å®¹æåºéï¼æ£å¦ä¹åæå±ç¤ºç飿 ·ã
ä½¿ç¨ Object.create()è°ç¨ Object.create()
ä¼å建ä¸ä¸ªæ°å¯¹è±¡ã该对象ç [[Prototype]]
æ¯è¯¥å½æ°ç第ä¸ä¸ªåæ°ï¼
const a = { a: 1 };
// a ---> Object.prototype ---> null
const b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1ï¼ç»§æ¿çï¼
const c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
const d = Object.create(null);
// d ---> nullï¼d æ¯ä¸ä¸ªç´æ¥ä»¥ null 为ååç对象ï¼
console.log(d.hasOwnProperty);
// undefinedï¼å 为 d 没æç»§æ¿ Object.prototype
ä¸å¯¹è±¡åå§åå¨ä¸ç __proto__
é®ç±»ä¼¼ï¼Object.create()
å
许å¨å建æ¶ç´æ¥è®¾ç½®å¯¹è±¡çååï¼è¿å
许è¿è¡æ¶è¿ä¸æ¥ä¼å对象ãè¿å
è®¸ä½¿ç¨ Object.create(null)
å建åå为 null
ç对象ãObject.create()
ç第äºä¸ªåæ°è½ç²¾ç¡®å°æææ°å¯¹è±¡ä¸æ¯ä¸ªå±æ§çç¹æ§ï¼èè¿ä¼æ¯ä¸æåååï¼
class Rectangle {
constructor(height, width) {
this.name = "Rectangle";
this.height = height;
this.width = width;
}
}
class FilledRectangle extends Rectangle {
constructor(height, width, color) {
super(height, width);
this.name = "Filled rectangle";
this.color = color;
}
}
const filledRectangle = new FilledRectangle(5, 10, "blue");
// filledRectangle ---> FilledRectangle.prototype ---> Rectangle.prototype ---> Object.prototype ---> null
å¨å®ä¹å¤æçç»§æ¿ç»ææ¶ï¼ç±»æä¾äºé常é«çå¯è¯»æ§åå¯ç»´æ¤æ§ãç§æå ç´ æ¯ååç»§æ¿ä¸æ²¡æç®åæ¿ä»£æ¹æ¡çç¹æ§ãç¶èï¼ç±»æ¯ä¼ ç»çæé 彿°çæ§è½è¦å·®ï¼èä¸ä¸æ¯ææ§ç¯å¢ã
ä½¿ç¨ Object.setPrototypeOf()è½ç¶ä¸é¢çæææ¹æ³é½ä¼å¨å¯¹è±¡å建æ¶è®¾ç½®ååé¾ï¼ä½æ¯ Object.setPrototypeOf()
å
许修æ¹ç°æå¯¹è±¡ç [[Prototype]]
å
é¨å±æ§ãå®çè³è½å¼ºå¶ä¸º Object.create(null)
åå»ºçæ ååç对象设置ååï¼æè
å°åå设置为 null
ç§»é¤å¯¹è±¡çååã
const obj = { a: 1 };
const anotherObj = { b: 2 };
Object.setPrototypeOf(obj, anotherObj);
// obj ---> anotherObj ---> Object.prototype ---> null
ç¶èï¼ä½ åºè¯¥å°½å¯è½å¨å建æ¶è®¾ç½®ååï¼å ä¸ºå¨æè®¾ç½®ååä¼ç ´å弿已ç»ä¸ºååé¾åè¿çææä¼åãå®å¯è½ä¼é æä¸äºå¼æä¸ºäºåä¼åèéæ°ç¼è¯ä½ ç代ç ï¼ä»¥ä½¿å ¶æç §è§èå·¥ä½ã
ä½¿ç¨ __proto__ 访é®å¨ææå¯¹è±¡é½ç»§æ¿äº Object.prototype.__proto__
setterï¼å®å¯ä»¥ç¨æ¥è®¾ç½®ç°æå¯¹è±¡ç [[Prototype]]
ï¼å¦æå¯¹è±¡ç __proto__
屿§æ²¡æè¢«è¦çï¼ã
è¦åï¼ Object.prototype.__proto__
访é®å¨æ¯éæ åçï¼ä¸å·²è¢«å¼ç¨ãä½ åºè¯¥å 乿»æ¯ä½¿ç¨ Object.setPrototypeOf
ã
const obj = {};
// 请ä¸è¦ä½¿ç¨è¯¥æ¹æ³ï¼ä»
ä½ä¸ºç¤ºä¾ã
obj.__proto__ = { barProp: "bar val" };
obj.__proto__.__proto__ = { fooProp: "foo val" };
console.log(obj.fooProp);
console.log(obj.barProp);
ä¸ Object.setPrototypeOf
ç¸æ¯ï¼å° __proto__
设置为é对象çå¼åªä¼è¢«å¿½ç¥ï¼èéæåºå¼å¸¸ãå®ä¹åªæç¨å¾®å¥½ä¸ç¹çæµè§å¨æ¯æãç¶èï¼å®æ¯éæ åçï¼å¹¶ä¸å·²è¢«å¼ç¨ãä½ åºè¯¥å 乿»æ¯ä½¿ç¨ Object.setPrototypeOf
ã
屿§ä½äºååé¾ä¸å±å¯è½ä¼å¯¹å±æ§çæ¥æ¾æ¶é´äº§çæ§è½æ¹é¢çè´é¢å½±åï¼è¿å¨æ§è½è³å ³éè¦ç代ç ä¸å¯è½ä¼éå¸¸ææ¾ãæ¤å¤ï¼å°è¯è®¿é®ä¸åå¨ç屿§å§ç»ä¼éåæ´ä¸ªååé¾ã
æ¤å¤ï¼å¨éå对象ç屿§æ¶ï¼ååé¾ä¸çæ¯ä¸ªå¯æä¸¾å±æ§é½å°è¢«æä¸¾ãè¦æ£æ¥å¯¹è±¡æ¯å¦å
·æå¨å
¶èªèº«ä¸ãè䏿¯å¨å
¶ååé¾ä¸çæä¸ªå°æ¹å®ä¹ç屿§ï¼åæå¿
è¦ä½¿ç¨ hasOwnProperty
æ Object.hasOwn
æ¹æ³ãé¤ [[Prototype]]
为 null
ç对象å¤ï¼ææå¯¹è±¡é½ä» Object.prototype
ç»§æ¿ hasOwnProperty
ââé¤éå®å·²ç»å¨ååé¾è¾ä¸å±å¤è¢«è¦çãæä»¬å°ä½¿ç¨ä¸é¢çå¾ç¤ºä¾ä»£ç æ¥è¯´æå®ï¼å
·ä½å¦ä¸ï¼
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype.addVertex = function (v) {
this.vertices.push(v);
};
const g = new Graph();
// g ---> Graph.prototype ---> Object.prototype ---> null
g.hasOwnProperty("vertices"); // true
Object.hasOwn(g, "vertices"); // true
g.hasOwnProperty("nope"); // false
Object.hasOwn(g, "nope"); // false
g.hasOwnProperty("addVertex"); // false
Object.hasOwn(g, "addVertex"); // false
Object.getPrototypeOf(g).hasOwnProperty("addVertex"); // true
注æï¼ä»
æ£æ¥å±æ§æ¯å¦ä¸º undefined
æ¯ä¸å¤çãè¯¥å±æ§å¾å¯è½åå¨ï¼ä½å
¶å¼æ°å¥½è®¾ç½®ä¸º undefined
ã
å¯¹äº Java æ C++ çå¼åè
æ¥è¯´ï¼JavaScript å¯è½æç¹ä»¤äººå°æï¼å ä¸ºå®æ¯å®å
¨å¨æãå®å
¨æ¯å¨æ§è¡æé´ç¡®å®çï¼è䏿 ¹æ¬æ²¡æéæç±»åãä¸åè¦ä¹æ¯å¯¹è±¡ï¼å®ä¾ï¼ï¼è¦ä¹æ¯å½æ°ï¼æé 彿°ï¼ï¼çè³å½æ°æ¬èº«ä¹æ¯ Function
æé 彿°çå®ä¾ãå³ä½¿ä½ä¸ºè¯æ³ç»æçâç±»âå¨è¿è¡æ¶ä¹åªæ¯æé 彿°ã
JavaScript ä¸çæææé 彿°é½æä¸ä¸ªè¢«ç§°ä¸º prototype
çç¹æ®å±æ§ï¼å®ä¸ new
è¿ç®ç¬¦ä¸èµ·ä½¿ç¨ã对åå对象çå¼ç¨è¢«å¤å¶å°æ°å®ä¾çå
é¨å±æ§ [[Prototype]]
ä¸ãä¾å¦ï¼å½ä½ æ§è¡ const a1 = new A()
æ¶ï¼JavaScriptï¼å¨å
åä¸å建对象ä¹åï¼å®ä¹ this
为该对象并æ§è¡ A()
ä¹åï¼è®¾ç½® a1.[[Prototype]] = A.prototype
ãç¶åï¼å½ä½ 访é®å®ä¾ç屿§æ¶ï¼JavaScript é¦å
æ£æ¥å®ä»¬æ¯å¦ç´æ¥åå¨äºè¯¥å¯¹è±¡ä¸ï¼å¦æä¸åå¨ï¼åå¨ [[Prototype]]
䏿¥æ¾ãä¼éå½å°æ¥è¯¢ [[Prototype]]
ï¼å³ a1.doSomething
ãObject.getPrototypeOf(a1).doSomething
ãObject.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething
ï¼ä¾æ¤ç±»æ¨ï¼ç´å°è¢«æ¾å°æ Object.getPrototypeOf
è¿å null
ãè¿æå³çå¨ prototype
ä¸å®ä¹çææå±æ§å®é
ä¸é½ç±ææå®ä¾å
±äº«ï¼å¹¶ä¸çè³å¯ä»¥æ´æ¹ prototype
çé¨åå
容ï¼ä½¿å¾æ´æ¹è¢«åºç¨å°ææç°æçå®ä¾ä¸ã
å¨ä¸é¢ç示ä¾ä¸ï¼å¦æä½ æ§è¡ const a1 = new A(); const a2 = new A();
ï¼é£ä¹ a1.doSomething
å®é
ä¸ä¼å¼ç¨ Object.getPrototypeOf(a1).doSomething
ââè¿ä¸ä½ å®ä¹ç A.prototype.doSomething
ç¸åï¼å³ Object.getPrototypeOf(a1).doSomething === Object.getPrototypeOf(a2).doSomething === A.prototype.doSomething
ã
äºè§£ååç»§æ¿æ¨¡åæ¯ä½¿ç¨å®ç¼å夿代ç çéè¦åºç¡ãæ¤å¤ï¼è¦æ³¨æä»£ç ä¸ååé¾çé¿åº¦ï¼å¨å¿ è¦æ¶å¯ä»¥å°å ¶åè§£ï¼ä»¥é¿å æ½å¨çæ§è½é®é¢ãæ¤å¤ï¼é¤éæ¯ä¸ºäºä¸æ°ç JavaScript ç¹æ§å ¼å®¹ï¼å¦åæ°¸è¿ä¸åºæ©å±åçååã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4