在JavaScript中,咱們每建立一個函數,都會有一個prototype(原型)屬性:這個屬性是一個指針,指向一個對象,對象的用途是包含能夠由特定類型的全部實例共享的屬性和方法瀏覽器
prototype 就是經過調用構造函數而建立的那個對象實例的原型對象。使用原型可讓全部對象實例共享它所包含的屬性和方法bash
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
person1.sayHello(); //"lilei:hello"
var person2 = new Person();
person2.sayHello(); //"lilei:hello"
console.log(person1.sayHello == person2.sayHello); //true
複製代碼
全部原型對象都會自動得到一個 constructor(構造函數)屬性,這個屬性包含一個指向 prototype 屬性所在函數的指針。如圖3-1:Person.prototype.constructor 指向 Person。函數
Person.prototype.constructor === Person // true
複製代碼
實例化的對象內部有一個看不見的__proto__指針,指向原型對象,__proto__只在瀏覽器內部使用,__對腳本則是徹底不可見的。雖然在全部實現中都沒法訪問到__proto__,但能夠經過 isPrototypeOf()方法來肯定對象之 間是否存在這種關係:this
console.log(Person.prototype.isPrototypeOf(person1)); //true
console.log(Person.prototype.isPrototypeOf(person2)); //true
複製代碼
全部對象的__proto__都指向其構造函數的prototypespa
person1.__proto__ === Person.prototype //true
複製代碼
Person.__proto__ === Function.prototype // true
Number.__proto__ === Function.prototype // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === Function.prototype // true
RegExp.__proto__ === Function.prototype // true
Error.__proto__ === Function.prototype // true
Date.__proto__ === Function.prototype // true
複製代碼
因此全部構造函數都繼承了Function.prototype的屬性及方法prototype
console.log(typeof Function.prototype) // function
console.log(typeof Object.prototype) // object
console.log(typeof Number.prototype) // object
console.log(typeof Boolean.prototype) // object
console.log(typeof String.prototype) // object
console.log(typeof Array.prototype) // object
console.log(typeof RegExp.prototype) // object
console.log(typeof Error.prototype) // object
console.log(typeof Date.prototype) // object
console.log(typeof Object.prototype) // object
複製代碼
Function.prototype.__proto__ === Object.prototype // true
Person.prototype.__proto__ === Object.prototype // true
Number.prototype.__proto__ === Object.prototype // true
Boolean.prototype.__proto__ === Object.prototype // true
String.prototype.__proto__ === Object.prototype // true
Array.prototype.__proto__ === Object.prototype // true
Function.prototype.__proto__ === Object.prototype // true
RegExp.prototype.__proto__ === Object.prototype // true
Error.prototype.__proto__ === Object.prototype // true
Date.prototype.__proto__ === Object.prototype // true
複製代碼
Object.prototype的__proto__?設計
Object.prototype.__proto__ === null // true
複製代碼
person1.constructor === Person.prototype.constructor //true
person1.constructor === Person //true
person1.name === Person.prototype.name //true
person1.age === Person.prototype.age //true
person1.sayHello === Person.prototype.sayHello //true
複製代碼
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg" ——來自實例
console.log(person2.name); // "lilei" ——來自原型
複製代碼
訪問person1.name時會在這個實例上搜索一個名爲 name的屬性。這個屬性若是存在,就返回,不存在 就到原型上去找。當爲對象實例添加一個屬性時,這個屬性就會屏蔽原型對象中保存的同名屬性;添加這 個屬性只會阻止咱們訪問原型中的那個屬性,但不會修改那個屬性指針
function Person(){}
Person.prototype.name = "lilei";
Person.prototype.age = 26;
Person.prototype.sayHello = function(){
console.log(this.name+":Hello!");
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
console.log(person1.name); // "Greg" ——來自實例
console.log(person2.name); // "lilei" ——來自原型
delete person1.name;
console.log(person1.name); // "lilei" ——來自原型
複製代碼
person1.name = "Greg";
person1.hasOwnProperty("name") //true
person2.hasOwnProperty("name") //false
複製代碼
當 person1 重寫name 屬性後返回 true,由於這時候 name 是一個實例屬性,而非原型屬性code
person1.name = "Greg";
person1.hasOwnProperty("name") //true
person2.hasOwnProperty("name") //false
console.log("name" in person1) //true
console.log("name" in person2) //true
複製代碼
function Person(){}
Person.prototype = {
constructor: Person,
name : "lilei",
age : 26,
friends : ["Jim", "Tom"]
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("hanmeimei");
console.log(person1.friends); //"Jim,Tom,hanmeimei"
console.log(person2.friends); //"Jim,Tom,hanmeimei"
console.log(person1.friends === person2.friends); //true
複製代碼
每一個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型 對象的內部指針。若是咱們讓原型對象等於另外一個類型的實例,會發生什麼?因此下一節《繼承》cdn
《JavaScript 高級程序設計》中文譯本 第三版