JSON字符串/原型鏈/構造函數

原型鏈

原型對象也是普通的對象,並且也有可能有自己的原型,如果一個原型對象的原型不爲null的話,我們就稱之爲原型鏈(prototype chain)。原型鏈是一個由對象組成的有限的對象鏈,用於實現繼承和屬性共享。

ECMAScript沒有類的概念。但是,重用[reuse]這個理念沒什麼不同(某些方面,甚至比class-更加靈活),可以由prototype chain原型鏈來實現。這種繼承被稱爲delegation based inheritance-基於繼承的委託,或者更通俗一些,叫做原型繼承。

簡單例子:

var a = {
  x: 10,
  calculate: function (z) {
    return this.x + this.y + z
  }
};
 
var b = {
  y: 20,
  __proto__: a
};
 
var c = {
  y: 30,
  __proto__: a
};
 
// 調用繼承過來的方法
b.calculate(30); // 60
c.calculate(40); // 80

原理很簡單:如果在對象b中找不到calculate方法(也就是對象b中沒有這個calculate屬性), 那麼就會沿着原型鏈開始找。如果這個calculate方法在b的prototype中沒有找到,那麼就會沿着原型鏈找到a的prototype,一直遍歷完整個原型鏈。記住,一旦找到,就返回第一個找到的屬性或者方法。因此,第一個找到的屬性成爲繼承屬性。如果遍歷完整個原型鏈,仍然沒有找到,那麼就會返回undefined。

注意一點,this這個值在一個繼承機制中,仍然是指向它原本屬於的對象,而不是從原型鏈上找到它時,它所屬於的對象。例如,以上的例子,this.y是從b和c中獲取的,而不是a。當然,你也發現了this.x是從a取的,因爲是通過原型鏈機制找到的。

如果一個對象的prototype沒有顯示的聲明過或定義過,那麼__prototype__的默認值就是object.prototype, 而object.prototype也會有一個__prototype__, 這個就是原型鏈的終點了,被設置爲null。


構造函數

原型鏈通常將會在這樣的情況下使用:對象擁有相同或相似的狀態結構(same or similar state structure) (即相同的屬性集合)與 不同的狀態值(different state values)。在這種情況下,我們可以使用構造函數(Constructor) 在 特定模式(specified pattern) 下創建對象。

除了創建對象,構造函數(constructor) 還做了另一件有用的事情—自動爲創建的新對象設置了原型對象(prototype object) 。原型對象存放於 ConstructorFunction.prototype 屬性中。

// 構造函數
function Foo(y) {
  // 構造函數將會以特定模式創建對象:被創建的對象都會有"y"屬性
  this.y = y;
 
// "Foo.prototype"存放了新建對象的原型引用
// 所以我們可以將之用於定義繼承和共享屬性或方法
// 所以,和上例一樣,我們有了如下代碼:
 
// 繼承屬性"x"
Foo.prototype.x = 10;
 
// 繼承方法"calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};
 
// 使用foo模式創建 "b" and "c"
var b = new Foo(20);
var c = new Foo(30);
 
// 調用繼承的方法
b.calculate(30); // 60
c.calculate(40); // 80
 
// 讓我們看看是否使用了預期的屬性
 
console.log(
 
  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true
 
  // "Foo.prototype"自動創建了一個特殊的屬性"constructor"
  // 指向a的構造函數本身
  // 實例"b"和"c"可以通過授權找到它並用以檢測自己的構造函數
 
  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo // true
 
  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true
 
);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章