2018-01-09 關于javascript原型鏈的思考 plus

s 深入理解原型和原型鏈?

構造函數

  • 構造函數的好處我們可以把我們的屬性和方法都添加到一個函數上面去
function User(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
}

var panda = new User('panda', 18, 'male');
console.log('panda:', panda);
//使用 new 的過程我們成為 ==實例化==

理解原型和原型鏈

怎么理解 prototype 和 __proto__ 啦?

  • 當我們使用普通的構造函數來搭建我們的方法的時候:
function User(name,age,gender){
    this.name = name ; 
    this.age = age ;
    this.gender = gender ;
    this.eat = function(){
      console.log('miao')  
    } ;
    this.greeting = function(){
        console.log('yo! my name is '+this.name)
    }
}

// 我們每次使用的時候都需要重新的實例化對象
// 這樣做都會重新的向內存申請新的空間,太浪費
var panda = new User();
  • 為了防止空間浪費的情況我們使用prototype的方法去設計我們的函數,這樣做
function A(){}

A.prototype.name = 'lala';

var a = new A();
var b = new A();

//首先打開你的瀏覽器
//我們可以先看看 __proto__ 是什么東西
console.log(a.__proto__);
console.log(a.constructor);

// 然后比較一下 a,b 的__proto__是否指向相同
console.log(a.__proto__ === b.__proto__);//true

  • 可以看到新實例化的對象的proto指向的是 一個 Object, a的構造器(constructor) 指向的就是我們創(chuàng)建的 A()

這里就需要解釋一下其中的 Object 是什么東東?還有 constructor 又是什么東西?

  • 記住這么一句話 在 JavaScript 所有的都是對象

這里有一個 case

new的時候js都干了什么

在 JavaScript 中,使用 new 關鍵字后,意味著做了如下四件事情:

  • 1:創(chuàng)建一個新的對象,這個對象的類型是 object;

  • 2:設置這個新的對象的內部、可訪問性和[[prototype]]屬性為構造函數(指prototype.construtor所指向的構造函數)中設置的;

  • 3:執(zhí)行構造函數,當this關鍵字被提及的時候,使用新創(chuàng)建的對象的屬性; 返回新創(chuàng)建的對象(除非構造方法中返回的是‘無原型’)。

  • 4:在創(chuàng)建新對象成功之后,如果調用一個新對象沒有的屬性的時候,JavaScript 會延原型鏈向止逐層查找對應的內容。這類似于傳統(tǒng)的‘類繼承’。

//打開你的瀏覽器的console 試試吧

//在JavaScript中我們都知道怎么創(chuàng)建 對象 Object
//其實 aa 創(chuàng)建的方法 只是 bb 創(chuàng)建 {} 的一個簡寫,其實我們是實例化了 一個對象。
var aa = {};
var bb = new Object();
console.log(a.constructor === b.constructor)//true
console.log(a.__proto__ === b.__proto__)//true

//我們可以看到他們的constructor 和 __proto__ 都是指向的相同的
//具體的內容,可以看到原型 __proto__ 指向的是一個 Object 然后繼承了一大堆方法

//測試數組
var a = [];
var a = new Array();
console.log('a',a)

上面涉及繼承,這個東西我們馬上談到

  • 使用 create 創(chuàng)建純潔的 啥也沒有繼承的 Object
//純潔的 object
var pure = Object.create({});
console.log('pure:',pure.__proto__)

//來對比一下變量 a
var a = {};
console.log('a:',a.__proto__)
//用這樣的方法創(chuàng)建的變量 pure 可以看到它什么都沒有繼承,查找它的 __proto__ 也什么都沒有,零污染

多級繼承鏈怎么實現

  • 理解了 prototype 終于要說怎么實現原型上面的繼承了。

  • 看代碼,我們先設計三個東東讓他們達成繼承關系

    • 一開始我們是三個對象函數
    • 常理來說 是這樣的繼承關系
      • Person --> Manmal --> Animal
function Animal() {
    
}

function Manmal() {
    
}

function Person() {
    
}
  • 我們首先賦予 Animal 一些能力(屬性和方法),然后來實例化一些 Animal

Animal() Code

function Animal(color,weight) {
    this.color = color;
    this.weight = weight;
}

Animal.prototype.eat = function(){
    console.log('mia mia mia...');
}

Animal.prototype.sleep = function(){
    console.log('hu lu lu...');
}

//繼承能力
var panda = new Animal('red',180);
var monkey = new Animal('yellow',20);

console.log(panda);
console.log(monkey);
console.log('a.eat === b.eat:',a.eat === b.eat);//true

//思考 我們怎樣讓我們的Burce來繼承原始的 Animal 的能力(屬性和方法)啦?
var Burce.L = new Person();
  • 接著上面代碼的問題,我們要讓 Burce.L 繼承 Animal 的能力, 因為 Burce 是一個 Person(),所以我們這樣做一下準備工作 ,讓我們的 Mannal 來 繼承 Animal ,思路齊了。開始工作
  • 代碼如下
//現在 Manmal 空空如也什么都還沒有
function Manmal() {
    
}

//要怎么繼承啦?可能我們開始接觸 prototype 最直接的方法是 將 Mannal的 prototype 直接的指向 Animal 的 prototype
Manmal.prototype = Animal.prototype; 
//這樣的方法可行,但是但我們修改 Manmal的繼承屬性的時候會污染我們的 Animal

//所以我們使用如下的方法,開辟一個無污染的空間
Manmal.prototype = Object.create(Animal.prototype);
var a = new Manmal();
//現在來看看 a 的情況
console.log(a.__proto__);
console.log(a.constructor);

//我們可以看到 __proto__ 指向了 Animal
//但是有個問題就是 這里的 constructor 應該指向我們的 new 的構造器 Manmal ,所以我們這里還得添加一行代碼

Manmal.prototype.constructor =  Manmal;

var b = new Manmal();
console.log(b.__proto__);
console.log(b.constructor);
console.log(b.eat);

//現在達到我們的想法了,將我們的 Manmal 繼承了 Animal 的 ==方法==

那么屬性要怎么繼承啦?這里就要使用call方法了
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call

function Manmal(color,weight){
    //綁定Animal的 顯性屬性的繼承方式 
    Animal.call(this,color,weight);
}
  • 整理一下關于 Manmal()的代碼

Manmal() Code

function Manmal(color,weight){
    //綁定Animal的 顯性屬性的繼承方式 
    Animal.call(this,color,weight);
}

Manmal.prototype = Object.create(Animal.prototype); 
Manmal.prototype.constructor =  Manmal;
//將繼承的constructor 再重新指回 Manmal constructor應該為父輩,這里指向了爺爺

//我們隨意給Manmal添加一個方法
Manmal.prototype.suckle = function(){
    console.log('biu biu biu...');
}

//test
var a = new Manmal('red',100);
console.log(a);
  • 同理整理一下關于 Person()的代碼

Person() Code

//修改Person

function Person(color,weight) {
    //綁定Animal的 本地屬性 
    Manmal.call(this,color,weight);
}

Person.prototype = Object.create(Manmal.prototype);
Person.prototype.constructor = Manmal;
Person.prototype.lie = function(){
    console.log('你不帥!');
}

var Bruce = new Person('yellow',120);
console.log('Bruce:',Bruce);
  • 最后 整合我們所有的代碼
function Animal(color,weight){
    this.color = color;
    this.weight = weight;
}

Animal.prototype.eat = function(){
    console.log('mia mia mia...');
}

Animal.prototype.sleep = function(){
    console.log('hu lu lu...');
}

function Manmal(color,weight){
    //綁定Animal的 顯性屬性的繼承方式 
    Animal.call(this,color,weight);
}

function Person(color,weight) {
    //綁定Animal的 本地屬性 
    Manmal.call(this,color,weight);
}


//使用繼承 manmal --> animal
Manmal.prototype = Object.create(Animal.prototype); 
Manmal.prototype.constructor =  Manmal;
//將繼承的constructor 再重新指回 Manmal constructor應該為父輩,這里指向了爺爺
Manmal.prototype.suckle = function(){
    console.log('biu biu biu...');
}


//修改Person
Person.prototype = Object.create(Manmal.prototype);
Person.prototype.constructor = Manmal;
Person.prototype.lie = function(){
    console.log('你不帥!');
}

var Bruce = new Person('yellow',120);
console.log('Bruce:',Bruce);

總結

幾個原型鏈之間的關系:

image
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容