JavaScript æ¯åæ²æå¯¦å class
ééµåçåæ
èªè¨ï¼æä»¥æå°é£äºåºæ¼é¡å¥ï¼class-basedï¼èªè¨ï¼å¦ Java æ C++ï¼èæ¯åºèº«çéç¼è
ä¾èªªææé»å°æãï¼å¨ ES2015 ææä¾ class
ééµåï¼ä½é£åªæ¯åèªæ³ç³ï¼JavaScript ä»ç¶æ¯åºæ¼ååï¼prototype-basedï¼çèªè¨ï¼ã
è¬å°ç¹¼æ¿ï¼JavaScript å°±åªæä¸å建æ§åï¼ç©ä»¶ãæ¯åç©ä»¶é½æä¸åé£èå
¶ä»ååï¼prototypeï¼çç§æå±¬æ§ï¼private propertyï¼ç©ä»¶ãååç©ä»¶ä¹æèèªå·±çååï¼æ¼æ¯ååç©ä»¶å°±é樣éçµï¼ç´å°æè¦ null
çºæ¢ï¼null
å¨å®ç¾©è£¡æ²æååã乿¯ååéï¼prototype chainï¼çæå¾ä¸åéçµã
幾乿æ JavaScript çç©ä»¶ï¼é½æ¯å¨ååéæé 端ç Object
實ä¾ã
éç¶é常被èªçºæ¯ JavaScript çä¸å缺é·ï¼ä½ååç¹¼æ¿æ¨¡å實éä¸ï¼æ¯å³çµ±ç classic æ¨¡åæ´å¼·å¤§ãèä¾ä¾èªªï¼ä½¿ç¨ååç¹¼æ¿æ¨¡å建æ§ä¸å classic æ¨¡åæ¯ç¸ç¶å®¹æçã
使ç¨ååéç¹¼æ¿ ç¹¼æ¿å±¬æ§JavaScript ç©ä»¶æ¯ä¸ãå ãåæ ç屬æ§ï¼ä¹å°±æ¯å®èªå·±ç屬æ§ï¼ä¸¦ææä¸åååç©ä»¶çéçµï¼ç¶ç©ä»¶è©¦åååä¸åç©ä»¶çå±¬æ§æï¼å ¶ä¸å æå°æ¾è©²ç©ä»¶ï¼ä¹æå°æ¾è©²ç©ä»¶çååãååçååâ¦â¦ç´å°æ¾å°ç¸ç¬¦åç屬æ§ï¼ææ¯å°éååéç尾端ã
åè¨»ï¼ éµç
§ ECMAScript æ¨æºç someObject.[[Prototype]]
æ¨è¨ï¼ç¨æ¼ææ´¾ someObject
çååãå¾ ECMAScript 2015 éå§ï¼ [[Prototype]]
ä½¿ç¨ Object.getPrototypeOf()
è Object.setPrototypeOf()
éå
©å訪åå¨ï¼accessorsï¼è¨ªåï¼ç忼鿍æºï¼ä½å大ç覽å¨å·²å¯¦åç __proto__
屬æ§ã
ä¸è¦æ someObject.[[Prototype]]
èå½å¼å±¬æ§ func.prototype
æ··æ·äºãå®å¨å½å¼è¢«ç¨ä½å»ºæ§åçæåï¼æå® [[Prototype]]
è¦åæ´¾å°ææç±çµ¦å®å½å¼å»ºç«çç©ä»¶å¯¦ä¾ï¼instanceï¼ãObject.prototype
屬æ§ä»£è¡¨äºååå±¬æ§ Object
ã
以䏿¯å試ååå±¬æ§ææç¼ççäºï¼
// å©ç¨å«æ a è b 屬æ§ç f å½å¼ï¼å»ºç«ä¸å o ç©ä»¶ï¼
let f = function () {
this.a = 1;
this.b = 2;
};
let o = new f(); // {a: 1, b: 2}
// æ¥èéå° f å½å¼çååæ·»å 屬æ§
f.prototype.b = 3;
f.prototype.c = 4;
// ä¸è¦å¯« f.prototype = {b:3,c:4}; å çºå®æç ´å£ååé
// o.[[Prototype]] æ b è c ç屬æ§ï¼{b: 3, c: 4}
// 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ã
// o éæååå屬æ§ãbãï¼ä½éè£¡æ²æè¢«è¨ªåå°ã
// é稱ä½ãproperty shadowingãã
console.log(o.c); // 4
// o æå±¬æ§ãcãåï¼æ²æï¼é£å°±æ¾ o çååççã
// o å¨ão.[[Prototype]]ãæå±¬æ§ãcãåï¼æï¼è©²æ¸å¼çº 4ã
console.log(o.d); // undefined
// o æå±¬æ§ãdãåï¼æ²æï¼é£å°±æ¾ o çååççã
// o å¨ão.[[Prototype]]ãæå±¬æ§ãdãåï¼æ²æï¼é£å°±æ¾ o.[[Prototype]] çååççã
// o.[[Prototype]].[[Prototype]] æ¯ Object.prototypeï¼é è¨ä¸¦æ²æå±¬æ§ãdãï¼é£åæ¾ä»çååççã
// o å¨ão.[[Prototype]].[[Prototype]].[[Prototype]]ãæ¯ nullï¼åæ¢æå°ã
// æ¾ä¸å°ä»»ä½å±¬æ§ï¼åå³ undefinedã
給ç©ä»¶è¨å®å±¬æ§ï¼æä»¤å ¶å»ºç«èªæç屬æ§ãéåè¡çºè¦åçå¯ä¸ä¾å¤ï¼å°±æ¯ç¢°ä¸ä»¥ getter æ setter ç¹¼æ¿çå±¬æ§æã
ç¹¼æ¿æ¹æ³Javascript ä¸¦æ²æå ¶ä»åºæ¼é¡å¥èªè¨é£è¬å®ç¾©çæ¹æ³ãå¨ Javascript 裡ï¼ä»»ä½å½å¼é½è½ä»¥å±¬æ§çæ¹å¼å å°ç©ä»¶ä¸ãä¸å被繼æ¿çå½å¼çè¡çºå°±åæ¯å ¶ä»å±¬æ§ä¸æ¨£ï¼å ¶ä¸ä¹å å«äºä¸è¿°ç property shadowingï¼å¨éç¨®æ æ³ä¸å«å method overridingï¼ã
ç¶ç¹¼æ¿å½å¼å·è¡æï¼this
弿åç¹¼æ¿çç©ä»¶ï¼è䏿¯å¨å½å¼å
§ææå±¬æ§çååç©ä»¶ã
var o = {
a: 2,
m: function () {
return this.a + 1;
},
};
console.log(o.m()); // 3
// å¨é裡å¼å« o.m æãthisãæçæ¯ o
var p = Object.create(o);
// p æ¯åå¾ o ç¹¼æ¿çç©ä»¶
p.a = 4; // å¨ p 建ç«å±¬æ§ãaã
console.log(p.m()); // 5
// å¼å« p.m æãthisãæçæ¯ p
// å æ¤å¨ p ç¹¼æ¿ o çå½å¼ m æï¼
// ãthis.aãæçæ¯ p.aï¼ä¹å°±æ¯ p çèªæå±¬æ§ãaã
ç¢çç©ä»¶åååéçå¹¾ç¨®æ¹æ³ å«æèªæ³çµæ§çç©ä»¶
var o = { a: 1 };
// æ°å»ºç o æåèªå·±ç [[Prototype]] ç¨±çº Object.prototype
// o èªå·±ä¸¦æ²æç¨±çºãhasOwnPropertyãç屬æ§
// è hasOwnProperty æ¯ Object.prototype çèªæå±¬æ§ã
// å æ¤ o å¾ Object.prototype ç¹¼æ¿äº hasOwnProperty
// Object.prototype ä½çºå
¶ååå¤äºå null
// o ---> Object.prototype ---> null
var a = ["yo", "whadup", "?"];
// å¾ Array.prototype ç¹¼æ¿çé£åï¼å«æè«¸å¦ indexOfãforEachâ¦â¦ä¹é¡çæ¹æ³
// ååéçèµ·ä¾å°±åï¼
// a ---> Array.prototype ---> Object.prototype ---> null
function f() {
return 2;
}
// å¾ Function.prototype ç¹¼æ¿çå½å¼ï¼å«æè«¸å¦ callãbindâ¦â¦ä¹é¡çæ¹æ³
// f ---> Function.prototype ---> Object.prototype ---> null
éé建æ§å
JavaScript 建æ§åï¼å°±ãåªãæ¯ãåã被 new éç®åå¼å«çå½å¼ã
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function (v) {
this.vertices.push(v);
},
};
var g = new Graph();
// g æ¯åæèãverticesãèãedgesã屬æ§çç©ä»¶ã
// å¨å·è¡ new Graph() æ g.[[Prototype]] æ¯ Graph.prototype çå¼ã
ç¨ Object.create
ECMAScript 5 å¼å
¥äºæ°æ¹æ³ï¼Object.create()
ãå¼å«éåæ¹æ³å°±å¯ä»¥å»ºç«æ°çç©ä»¶ãéåç©ä»¶çååï¼çºå½å¼ç第ä¸å忏ã
var a = { a: 1 };
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (inherited)
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty);
// undefined, because d doesn't inherit from Object.prototype
使ç¨ééµå class
ECMAScript 2015 å¼å
¥äºæ°çé¡å¥å¯¦åãå管å°é£äºåºæ¼é¡å¥çéç¼è
ä¾èªªï¼éç¨®çµæ§é«ä»¤ä»åæå°çæï¼å®åä¾èä¸ä¸æ¨£ãJavaScript ä¾èæ¯åºæ¼ååçãæ°çééµåå
æ¬ class
ãconstructor
ãstatic
ãextends
ãsuper
ã
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);
æè½
ååéä¸ç屬æ§çæ¥è©¢æéï¼å¯è½æå°æè½æè² é¢å½±é¿ï¼å°ç¨å¼ç¢¼ä¹å èç¢çæé¡¯åé¡ãå¦å¤ï¼è©¦åå°æ¾ä¸åå¨ç屬æ§ï¼å°±ä¸å®æéæ·æ´åååéã
æ¥èï¼å¨è¿ä»£ç©ä»¶å±¬æ§æï¼æ¯åååéçæè屬æ§é½ææåºä¾ã
è¦æª¢æ¥ç©ä»¶æ¬èº«ææ²ææå®ç屬æ§ãä¹ä¸éè¦æ¥æ¾æ´åååéæï¼ä½ å¿
é 使ç¨ç± Object.prototype
ç¹¼æ¿ç hasOwnProperty
æ¹æ³ã
console.log(g.hasOwnProperty("vertices"));
// true
console.log(g.hasOwnProperty("nope"));
// false
console.log(g.hasOwnProperty("addVertex"));
// false
console.log(g.__proto__.hasOwnProperty("addVertex"));
// true
å¨ JavaScript è£¡é¢ hasOwnProperty
æ¯å¯ä¸è½èçãä¸ä¸éæ·æ´åååéçæ¹æ³ã
註ï¼å¦æåªææª¢æ¥å±¬æ§æ¯å¦çº undefined
æ¯ä¸å¤ çã該屬æ§å¯è½åå¨ï¼åªæ¯æ¸å¼è¢«è¨å®çº undefined
ã
ä¸å常è¦ç誤ç¨ï¼æ¯æ´å
Object.prototype
æå
¶ä»å
§å»ºçååã
é種æå·§ç¨±çºç´åè£ä¸ï¼monkey patchingï¼ï¼å®æç ´å£å°è£ï¼encapsulationï¼ãå管æäºåæ¡è¿çæ¡æ¶å¦ Prototype.js æé麼åï¼ä½å®å䏦䏿¯ä»¥é¡å¤ç鿍æºåè½ï¼æäºå §å»ºé¡åç好çç±ã
æ´å
å
§å»ºååçå¯ä¸åççç±ï¼å°±æ¯ååç§»æ¤æ°ç JavaScript 弿çåè½ï¼ä¾å¦ Array.forEach
ã
B
è¦ç¹¼æ¿èª A
ï¼
function A(a) {
this.varA = a;
}
// å¨ A.prototype.varA ææ°¸é 被 this.varA 鬼é±ï¼shadowedï¼çæ
æ³ä¸ï¼
// æ varA å
å¨çµ¦å®å½å¼çååå
§ï¼å
¶æç¾©çºä½ï¼
A.prototype = {
varA: null, // é£éä¸è½å çºååå¥é½æ²ä½ï¼å°±æ varA ææ·åï¼
// ä¹è¨±ä»æç®è¦åé
é±èé¡å¥ç空éï¼ä»¥ä¾¿å¯¦è¡æä½³åï¼
// https://developers.google.com/speed/articles/optimizing-javascript#Initializing instance variables
// 妿 varA æ²æéå°æ¯å實ä¾ä½å®ä¸åå§åï¼é£éº¼ä¸å°±è¦è®ææçï¼
doSomething: function () {
// ...
},
};
function B(a, b) {
A.call(this, a);
this.varB = b;
}
B.prototype = Object.create(A.prototype, {
varB: {
value: null,
enumerable: true,
configurable: true,
writable: true,
},
doSomething: {
value: function () {
// override
A.prototype.doSomething.apply(this, arguments); // call super
// ...
},
enumerable: true,
configurable: true,
writable: true,
},
});
B.prototype.constructor = B;
var b = new B();
b.doSomething();
é黿¯ï¼
.prototype
ãObject.create()
ç¹¼æ¿ãprototype
è Object.getPrototypeOf
JavaScript å°é£äºå¾ Java æ C++ å¸éä¾ç人ä¾èªªï¼å¯è½ææé»å°æï¼å çºå®åæ ãæ°¸é æ¯å·è¡çæ ï¼all runtimeï¼ãéå®å ¨æ²æ classãä¸åé½åªæ¯å¯¦ä¾ï¼ç©ä»¶ï¼ãå³ä½¿æ¯ãclassãééµåï¼ä¹åªæ¯å½å¼ç©ä»¶ã
ä½ å¯è½æ©å°±ç¼ç¾æåç function A
æååçº prototype
çç¹æ®å±¬æ§ãéåç¹æ®å±¬æ§æéé new
éç®åéè¡ä¹ãååç©ä»¶çåç
§ï¼æææ°å¯¦ä¾ç [[Prototype]]
屬æ§è¤è£½å°è©²ç©ä»¶å
§é¨ãæ¯æ¹èªªå¨ä½ var a1 = new A()
æï¼JavaScript å¨è¨æ¶é«è£¡é¢å»ºç«ç©ä»¶å¾ãéæéè¡å·²ç¶å®ç¾©å¥½ this
çå½å¼ A()
åï¼æè¨å® a1.[[Prototype]] = A.prototype
ã卿¥è訪å實ä¾ç屬æ§åï¼JavaScript é¦å
æç´æ¥æª¢æ¥ç©ä»¶ç實ä¾å±¬æ§æ¯å¦åå¨ãå¦ææ²æï¼å°±æª¢æ¥ [[Prototype]]
ãä¹å°±æ¯èªªï¼å¨ prototype
å®ç¾©çæ±è¥¿ï¼è½å¤ ææå°å
±äº«çµ¦å實ï¼çè³ï¼å¦ææ³ç話ï¼éå¯ä»¥æ¹è®ä¸¦é¡¯ç¾æ¼ç¾æå¯¦ä¾ä¸ã
å¦ä¸ä¾æç¤ºï¼é¦å
var a1 = new A(); var a2 = new A();
æ¥è a1.doSomething
çè©±ï¼æåç
§å° Object.getPrototypeOf(a1).doSomething
ï¼ä»æèæ©å°±å®ç¾©å¥½ç A.prototype.doSomething
ç¸åï¼ä¾å¦ï¼ Object.getPrototypeOf(a1).doSomething == Object.getPrototypeOf(a2).doSomething == A.prototype.doSomething
.
ç°¡èè¨ä¹ï¼prototype
éå°åå¥ï¼è Object.getPrototypeOf()
åå實ä¾ç¸åã
[[Prototype]]
鿏æ§å°éçµèï¼ä¾å¦èªª a1.doSomething
, Object.getPrototypeOf(a1).doSomething
, Object.getPrototypeOf(Object.getPrototypeOf(a1)).doSomething
鿍£ï¼ç´å°æ¾åº Object.getPrototypeOf
æåå³ nullã
å æ¤ç¶ä½ ï¼
JavaScript å ¶å¯¦æï¼
var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);
æå¶ç¾é樣ï¼
æï¼å®æª¢æ¥äº o
ææ²æ someProp
屬æ§ãå¦ææ²æï¼å°±æª¢æ¥ Object.getPrototypeOf(o).someProp
ï¼åæ²æå°±æª¢æ¥ Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp
ï¼ä¾æ¤é¡æ¨ã
卿°å¯«è¤éçå¯ç¨ç¨å¼ç¢¼ä¹åï¼çè§£ååç¹¼æ¿æ¨¡åå¾éè¦ãå¦å¤ï¼è«æ³¨æç¨å¼ç¢¼å §ååéçé·åº¦ãå¿ è¦ææç ´å®åï¼ä»¥é¿å æ½å¨çæè½åé¡ãåä¾ï¼é¤éè¦èç 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