在這之前一直看到 [[Prototype]]
在看過克服 JS 奇怪的地方,就有提到原型鍊。
在了解這樣的概念之後,就深深的覺得 JavaScript 在語言界的獨特性。
是用不一樣的思維創造的語言。
Tony 覺得這是最重要的靈魂,一起來了解一下。
[[Prototype]] 是物件的一個內部特性,單純是對另一個物件的參考。在建立物件時,[[Prototype]] 不會是 null。
BUT,空的 [[Prototype]] 還是存在,但不常見。
var myObject = {
a: 2
};
myObject.a; // 2
經由 RHS 來找 a 時。
會用 [[Get]] 作業。
到底什麼是[[Prototype]]
var anotherObject = {
a: 2
};
var myObject = Object.create(anotherObject);
myObject.a; // 2
你會發現 myObject 其實沒有 a 的屬性,所以 [[Get]] 拿不到。
但是藉由 [[Prototype]] 往上一層尋找,在 anotherObject 上面找到了 a 屬性,就回傳這個值 2。
但是如果沒有這個值呢?
就會往全域找?不一定,因為他是沿著 [[Prototype]] 的串鏈找的,這個鍊稱為原型鍊 ( Prototype Chain )。
Object.create(..) 會在後面解說。
這邊請先當成 myObject 來自於 anotherObject,是目前 [[Prototype]] 會指向的位置。
以下兩個方法,都可以檢查屬性是否在串鏈上。
for ( var k in myObject ){
console.log( "found: " + k );
}
// found: a
("a" in myObject ); // true
但是原型鍊的終點是?
每一條正常的就是 Object.prototype,這是所有物件的起源。
myObject.foo = "bar";
所以,就算更高更遠的原型鍊的彼方,還是有 foo 屬性會怎樣?
一樣,若有 foo 在 myObject 上。就設定值。
這個現象叫做遮蔽。
這時候出現了三種情況。
若在串鏈上更高的位置,找到了
正常只有第一種,也是一般覺得會發生的。
但第二第三種想要遮蔽呢?
請用 Object.defineProperty(..) 新增 foo 屬性。
遮蔽可能隱含的發生,要小心。如下程式碼。
var anotherObject = {
a: 2
};
var myObject = Object.create( anotherObject );
anotherObject.a; // 2
myObject.a; // 2
myObject.hasOwnProperty( "a" ); // false 這邊為止都正常。
myObjcet.a++; // oops!
anotherObject.a; // 2
myObject.a; // 3 加到自己本身?!
myObject.hasOwnProperty( "a" ); // true!
因為 myObject.a++
請看成 myObject.a = myObject.a + 1
。
2
的值。3
。若想遞增 anotherObject.a,就 anotherObject.a++ 吧。
JavaScript 沒有類別。
是非常少數能夠創建一個物件,但完全不用類別的語言之一。
先說,這是一個神奇的行為,但因為巧合,就大家一直用。
其實是背後的邏輯恰好碰上。
function foo() {
// ...
}
Foo.prototype; // { }
這個物件被稱為 Foo 的原型 ( prototype )。
但其實是命名恰好碰上用 prototype。( 那為什麼不設成關鍵字呢? )
那他是什麼?
var a = new Foo();
Object.getPrototypeOf( a ) === Foo.prototype; // true
在 new 得時候。
[[Prototype]] 連結已產生,是連結到 Foo.prototype。