什么是原型
js中的原型指的是一個對象可以從另一個對象繼承特性吝羞。每個對象都有一個原型對象凉翻,對象以其原型對象為模板筐咧,繼承其屬性,方法噪矛。原型對象也有自己的原型對象量蕊,這樣一層一層,通常稱為原型鏈艇挨。
準(zhǔn)確來說残炮,這些屬性和方法,定義在對象的構(gòu)造函數(shù)(constructor functions)之上的prototype屬性上面缩滨,而不是對象實(shí)例本身势就。
js中鏈接對象實(shí)例和原型的是_proto_,它是從構(gòu)造函數(shù)的prototype派生的泉瞻,之后上溯到原型鏈,在構(gòu)造器中找到這些屬性和方法苞冯。
js中不是所有的對象都可以作為原型對象袖牙,每個對象都是繼承自O(shè)bject,但是我們主動設(shè)置一個對象的原型為另一個對象舅锄。
prototype屬性
繼承的屬性和方法被定義在prototype屬性上鞭达,prototype屬性的值是一個對象。
constructor屬性
每個實(shí)例對象都從原型中繼承了一個constructor屬性皇忿,該屬性指向了用于構(gòu)造此實(shí)例對象的構(gòu)造函數(shù)畴蹭。
構(gòu)造函數(shù),原型鳍烁,實(shí)例之間的關(guān)系
下面我們將通過一些例子來看一下
//構(gòu)造函數(shù)1
function Person( name,age ){
this.name = name;
this.age = age;
};
//構(gòu)造函數(shù)2
function Test (){
}
//實(shí)例1
var person1 = new Person("小明", 21);
//原型鏈為: person1 ====> Person ====> Object ====> null
console.log(person1.constructor);
/*output:
person1.constructor指向構(gòu)造函數(shù)Person
? Person(name, age) {
this.name = name;
this.age = age;
}
*/
console.log(person1.__proto__);
console.log(Person.prototype);
/*output:
{
constructor: ? Person(name, age)
__proto__: Object
}
*/
console.log(person1.__proto__ === Person.prototype); //true
//實(shí)例2叨襟;
var person2 = new Test();
//把實(shí)例person1作為person2的原型
person2.__proto__ = person1;
//原型鏈為: person2 ====> person1 ===> Person ===> Object ====>null
console.log(person2.name) //小明,繼承自person1
console.log(person2.constructor);
/*output:
? Person(name, age) {
this.name = name;
this.age = age;
}
*/
console.log(person2.__proto__);
/*output:
{
Person
age: 21
name: "小明"
__proto__:
{
constructor: ? Person(name, age)
__proto__: Object
}
}
*/
console.log(person2.__proto__.__proto__ === Person.prototype); //true
//實(shí)例3
//create() 實(shí)際做的是從指定原型對象創(chuàng)建一個新的對象幔荒。這里以 person1 為原型對象創(chuàng)建了 person3 對象糊闽。
var person3 = Object.create(person1);
//原型鏈為: person3 ====> person1 ===> Person ===> Object ====>null
console.log(person3.__proto__);
/*output:
{
Person
age: 21
name: "小明"
__proto__:
{
constructor: ? Person(name, age)
__proto__: Object
}
}
*/
不改變對象的原型鏈繼承另一個對象的方法
//構(gòu)造函數(shù)1
function Person( name,age ){
this.name = name;
this.age = age;
};
//構(gòu)造函數(shù)2
function Test (){
}
//方法一:
var person4 = new Test();
//用call或者apply來改變this,在person4的作用域里面去執(zhí)行Person
//Person.call(person4);
Person.apply(person4);
console.log(person4.__proto__);
/*
constructor: ? Test()
__proto__: Object
*/
//方法二: 可以直接在構(gòu)造函數(shù)里面使用apply或者call
//比如:
function Test (){
Person.call(this);
}
四個拓展原型鏈的方法
new操作符做了什么事情
//new 的過程
var obj = new Object(); //創(chuàng)建一個新對象
obj.__proto__ = A.prototype; //讓obj的__proto__指向A.prototype
A.call(obj) //在obj的作用環(huán)境執(zhí)行構(gòu)造函數(shù)的代碼,使this指向obj
return obj //返回實(shí)例對象