一:原型鏈
先說(shuō)三個(gè)js原型鏈通用規(guī)則
1、每個(gè)對(duì)象都有__proto__屬性,指向它的構(gòu)造函數(shù)的prototype(不過(guò)這個(gè)__proto__由兼容性問題,在IE11以前用不了)
2、每個(gè)函數(shù)都有一個(gè)prototype屬性
3、函數(shù)也是對(duì)象
先驗(yàn)證第一第二個(gè)規(guī)則
function Person(){}
Person.prototype.age = 12;
let justin = new Person();
console.log(justin.__proto__ === Person.prototype); // true
console.log(justin.age);//12
原型鏈
所謂原型鏈,也就是,查找對(duì)象的屬性或方法時(shí)會(huì)從
對(duì)象本身 => 對(duì)象的構(gòu)造函數(shù).prototype =>
構(gòu)造函數(shù)的(父)構(gòu)造函數(shù).prototype(如果中間有繼承的話) =>...=>
Object.prototype => null
在上面的代碼中查找age的時(shí)候,原型鏈?zhǔn)乔逦液?jiǎn)單的,也就是
justin => Person.prototype => Object.prototype => null
因?yàn)閖ustin上,沒有age屬性,age屬性是在Person.prototype上的,
且 justin.__proto__ === Person.prototype,所以
從justin => Person.prototype(justin.__proto__) 這一步是沒有問題
那我們來(lái)驗(yàn)證一下,Person.prototype => Object.prototype 這一步
function Person(){}
Person.prototype.age = 12;
let justin = new Person();
console.log(justin.__proto__ === Person.prototype); // true
console.log(justin.age);//12
// ---------- 以下是新加的內(nèi)容-------------
// 我們知道justin.__proto__ === Person.prototype; // 全等號(hào)
console.log(jusin.name);// undefined;
Object.prototype.name = 'bob'; // 注意這里我們?cè)O(shè)置的是Object.prototype.name
console.log(justin.name);// bob
console.log(Person.prototype.__proto__ === Object.prototype);// true
console.log(Object.prototype.__proto__ === null); // 全等號(hào)
所以justin原型鏈的大致結(jié)構(gòu)圖如下,如果Person中間有繼承其他類的話,則會(huì)在Object.prototype
和Person.prototype之間有相應(yīng)的.prototype對(duì)象插入其中,具體不細(xì)說(shuō)了。
justin原型鏈圖片

__proto__兼容性

二:繼承
js如何實(shí)現(xiàn)繼承?我們修改一下上面的代碼
/**
* 第一種方法
*/
function Person(){}
Person.prototype.age = 1;
Person.prototype.boss = '王多魚';
Person.prototype.sayHello = function(){
console.log('hello');
}
function ZuAnRen(){}
ZuAnRen.prototype.sayHello = function(){
console.log('wdnmd');
}
// 我們?cè)煲粋€(gè)祖安人
let za1 = new ZuAnRen();
// 如何讓ZuAnRen繼承Person呢?
// 目前za1的原型鏈?zhǔn)沁@樣的: za1 => ZuAnRen.prototype => Object.prototype => null
// 要讓ZuAnRen繼承Person,也就是在ZuAnRen.prototype => Object.prototype之間插入一個(gè)Person.prototype
// 而 ZuAnRen.prototype 也是個(gè)對(duì)象,所以也有__proto__屬性
// 所以試試這樣
ZuAnRen.prototype.__proto__ = Person.prototype;
console.log(za1.boss);// 王多魚 說(shuō)明我們成功了!
za1.sayHello(); // wdnmd
/**
* 第二種方法(使用class和extends,不細(xì)說(shuō))
*/
三:詳細(xì)扒拉function中的proto
由于function也是一個(gè)對(duì)象,所以也有一個(gè)__proto__對(duì)象
所以,像上面的Person.__proto__等于誰(shuí)呢?
答案是 Function.prototype
因?yàn)閒unction就是由Function創(chuàng)建的(這里注意,后面的Function首字母大寫)
那Function.__proto__呢?
答案還是Function.prototype
function Person(){
}
console.log(Person.__proto__ === Function.prototype); // true
console.log(Function.__proto__ === Function.prototype); // true
最后補(bǔ)全原型鏈一張圖
