紅寶書總結-原型模式

_會笑的鸚鵡_發表於2019-05-06

原型模式

紅寶書147頁 (以下例項均摘抄自紅寶書,不全,例項可直接翻書)

  • 一圖說明一切:

紅寶書總結-原型模式

  • 所有的建構函式都會有一個prototype屬性(無需定義),指向該建構函式的原型物件(prototype是指標不是物件!)
  • 所有原型物件都會有一個constructor屬性(無需定義),指向其對應的建構函式(constructor是指標不是物件!)
  • 建構函式生成的例項都會有一個_proto_屬性(無需定義,對開發者不可見),指向建構函式的原型物件

相關函式

  • 無法訪問_proto_,但可以通過isPrototypeOf()確定物件與原型物件的關係:
Person.prototype.isPrototypeOf(person1) //true
複製程式碼
  • Object.getPrototypeOf(),可以返回_proto_的值:
Object.getPrototypeOf(person1) == Person.prototype //true
複製程式碼

同名覆蓋

  • 當為物件例項新增一個屬性時,這個屬性就會遮蔽原型物件中儲存的同名屬性,但不會修改那個屬性。使用delete操作符可以完全刪除例項屬性,但不能刪除原型屬性及變數

  • hasOwnProperty()可以檢測一個屬性是存在於例項還是存在於原型。只有當給定屬性存在於物件例項中,才會返回true:

person1.hasOwnProperty("name")
複製程式碼
  • Object.getOwnPropertyDescriptor() 用於獲取例項屬性的描述符,如果要取得原型屬性的描述符,必須在原型物件上呼叫Object.getOwnPropertyDescriptor(該例項摘自MDN,無原型物件的例子):
var o, d;

o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, "foo");
// d {
//   configurable: true,
//   enumerable: true,
//   get: /*the getter function*/,
//   set: undefined
// }

o = { bar: 42 };
d = Object.getOwnPropertyDescriptor(o, "bar");
// d {
//   configurable: true,
//   enumerable: true,
//   value: 42,
//   writable: true
// }

o = {};
Object.defineProperty(o, "baz", {
  value: 8675309,
  writable: false,
  enumerable: false
});
d = Object.getOwnPropertyDescriptor(o, "baz");
// d {
//   value: 8675309,
//   writable: false,
//   enumerable: false,
//   configurable: false
// }

複製程式碼

原型與in操作符

  • in操作符的使用:單獨使用和for-in迴圈中使用
  1. 單獨使用:in操作符會在通過物件能夠訪問給定屬性時返回true,無論該屬性存在於例項中還是原型中
function Person(){}
Person.prototype.name = "li"
var person1 = new Person();
alert("name" in person1) //true
複製程式碼
  • object.hasOwnProperty()可判斷屬性是否在例項上,與in結合使用,可以寫出判斷屬性是否在原型上的函式:
function hasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
}
複製程式碼
  1. for-in迴圈,返回的是所有能夠通過物件訪問的、可列舉的(enumerated)屬性,其中既包括存在於例項中的屬性,也包括存在於原型中的屬性。如果有例項屬性遮蔽了原型屬性,且該原型屬性為不可列舉的,該實力屬性也會在for-in迴圈中返回。
  • 正常情況下,開發人員直接定義的屬性都是可列舉的

  • 要取得物件上所有可列舉的例項屬性,可以使用Object.keys()方法,其返回一個包含所有可列舉屬性的字串陣列

紅寶書總結-原型模式

紅寶書總結-原型模式

  • 如果想要得到所有例項屬性,無論它是否可列舉,都可以使用Object.getOwnPropertyNames()方法
var keys = Object.getOwnPropertyNames(Person.prototype);
alert(keys);//"constructor,name,age"
複製程式碼

更簡單的原型語法

  • 直接用物件字面量形式建立新物件:
Person.prototype = {
    name:"li",
    age: 29
}
複製程式碼
  • 但是這樣等同於完全重寫了prototype物件,因此constructor屬性也就變成了新物件的constrctir屬性(指向Object建構函式),不再指向Person函式。所以,可以專門寫個constructor:
Person.prototype = {
    constructor : Person,
    ...
}
複製程式碼
  • 這種方法重設的constructor屬性會導致其Enumerable特性被設定為true,預設情況下,原生的constructor屬性是不可列舉的。可以使用Object.defineProperty():
Object.defineProperty(Person.prototype, "constructor", {
    enumrable:false,
    value:Person
})
複製程式碼

原型的動態性

  • 正常情況下,給原型定義屬性或方法,會在例項上實時展現;但是如果重寫了原型,例項中的指標不會指向重寫的原型
function Person(){}
var friend = new Person();
Person.prototype = {
    constructor:Person,
    name:"li"
}
friend.name //undefined
複製程式碼

相關文章