2018年3月面試心得《原型、原型鏈》

以前的文章地址:
2018年3月面試心得《跨域問題》
2018年3月面試心得《上下文,做用域》前端

想了半天,我仍是對原型下手了。
近期面試的小夥伴們確定也是面臨着很多原型的問題。es6

「請你簡單描述一下原型。」
——原型就是爸爸,原型鏈就是爸爸的基因。
「如何實現繼承?」 ——es6的extends。 「es5呢?」
——………(臉上笑嘻嘻,內心fuuuuuuuuuuuck!!!)

我想應該有很多轉專業到前端來的小夥伴跟我同樣,基礎弱的一筆,抓了幾個面試題刷了刷,完事英勇的衝了出去,昂首挺胸的被問幾句,答上來了自信心爆表,可是面試官再問細一點,立馬就蔫巴了~
不得不說,大廠都會抓着你基礎死勁問,由於他們認爲基礎決定一切。(他們是否是這麼認爲的我也不知道,可是給我感受就是這樣……)
接下來,咱們要好好的來鞏固一下原型的基礎啦。面試

首先,咱們先玩個函數。

// 我先個你一個兒子的設計圖
function 兒子(name, age, isGay) {
    this.name = name;
    this.age = age;
    this.isGay = true;
}

// 如今我要開始造兒子了!!!
var myson = new 兒子('小明', 50, false)

// 如今打印一下咱們的myson
//{name: "小明", age: 50, isGay: true}

// 臥槽怎麼回事,我兒子怎麼是個gay!不行!
myson.isGay = false

// 好了這下舒坦了 嘿嘿嘿嘿

上面的這個就是構造函數,咱們也能夠叫他爲兒子生成器,或者圖紙。
咱們拿着圖紙去生成不一樣的兒子,兒子你又能夠給他新的屬性等等~你能夠diy~
是否是頗有意思。
好了咱們進入正題。segmentfault


普通對象和函數對象

JavaScript中萬物皆對象,但對象之間也是有區別的。分爲普通對象函數對象跨域

咱們大前端是不怕單身的,沒對象能夠new一個。
在看代碼的時候,常常會看到這些東西。函數

var a = new Object;
var b = new funxtion() {……}

這就是被咱們new出來的對象。
很明顯,上面的是普通對象,下面的是函數對象。性能

普通對象若是加上了prototype的屬性,那麼就變成了原型對象。
每一個函數對象建立的時候,都會自帶一個prototype的屬性,這個屬性至關於一個指針,指向他自己的原型對象,這個原型對象裏包含着自定義的方法屬性學習

好了,讓咱們來實踐一下,首先咱們要作一隻貓咪和一隻狗狗。this

var miao;
miao.prototype = {
    name = "大蛋蛋",
    age = 1
}
function dog(name, age){
    this.name = name,
    this.age = age
}

// 如今咱們把貓狗的圖紙畫好了,上面是原型對象的方式,下面是函數對象,接下來咱們就能夠來建立一些貓貓狗狗了。

咱們停一下

昨晚在我寫到這裏的時候,去看了一本書,上面寫着其實js的繼承,其實並不該該叫繼承。
在其餘語言中,繼承是屬於複製。es5

創造了一個爸爸,那麼繼承就是我複製了不少爸爸出來,每一個爸爸都同樣的。
固然你也能夠給你創造的每一個爸爸一些單獨的屬性,這個爸爸會作飯,那個爸爸會釣魚。

在you don`t know js裏面的第五章寫着:

原本設計js語言的時候並無想將它作的太過複雜。
經過new的函數調用並無創造關聯,這個關聯只是一個**意外的反作用**。

這個觀點我目前還不是太清楚對錯,可是咱們能夠暫時先這麼理解一下。

若是說其餘語言的繼承,就是複製的話,你創造一個爸爸圖紙,能夠做出不一樣的爸爸。

那麼js的理解應該就是,你創造一個爸爸,而且生出一堆兒子,每一個兒子都 能夠擁有爸爸給孩子的東西,例如釣魚、作飯(爸爸的方法)。

爲何會擁有他的方法呢?

由於在兒子尚未學習這個方法的時候,咱們班主任讓兒子去釣魚,那麼兒子不會,就會向上查找去叫爸爸,若是爸爸有這個技能,咱們就能夠成功完成任務了。

如今咱們來用作簡單的語言來闡述一下原型和原型鏈。
什麼是原型?那就是爸爸。
什麼是原型鏈?那就是爸爸和兒子的關係。

不知道這麼解釋會不會有點牽強,不過這確實能夠有助於咱們去實踐下一步。


如今開始真正的實踐。

咱們仍是簡單去作一個爸爸吧。

function 爸爸(name) {
    // 如今我給爸爸丟上一些方法
    // 給孩子命名
    this.name = name;
    // 爸爸願意交給兒子能夠釣上來你想要的魚
    this.goFishing = function(fis) {
        return fis
    }
}
// 如今咱們來創造兒子
var 兒子小明 = new 爸爸('小明')

兒子小明.name //"小明"
兒子小明.goFishing('章魚') //"章魚"

// 爸爸沒有直接較
爸爸.prototype.cook = function () {
    ['米飯', '爆炒魷魚', '番茄蛋湯'].forEach(i => console.log(i))
}
兒子小明.cook()
// 米飯 爆炒魷魚 番茄蛋湯

如今咱們打印一下小明兒子。
兒子裏面有:{name: "小明", goFishing: ƒ}
這是爸爸直接給兒子的東西。
那麼爸爸還沒給兒子,兒子卻可使用的到哪裏去了呢?

咱們往下再看,有一個__proto__
在這裏面,就能發現爸爸的cook。

因此爸爸的獨門絕技丟在了prototype裏面,這裏面是兒子不須要學習卻能夠直接使用的獨門絕技~

構造函數屬性(constructor)

這個又是什麼呢?
其實在剛剛咱們打印兒子小明的時候,在cook下面,有一個constructor的東西,就是這玩意。
仍是剛剛的代碼,如今跟着我一塊兒打印一下兒子小明.constructor
如今直接把爸爸打印出來了。

這個怎麼理解呢……
我找到了一句話。

在默認狀況下,全部的原型對象都會自動得到一個 constructor(構造函數)屬性,這個屬性(是一個指針)指向 prototype 屬性所在的函數(Person)

好了,就按照這句話這麼理解的話,咱們能夠理解爲:

全部的兒子都會有一個constructor的屬性,這個屬性指着能夠獲取爸爸獨門絕技(prototype)的那個爸爸。

如今我叫他找爸爸屬性……

如今咱們再建立一個女兒

var 女兒小花 = new 爸爸('小花')

兒子小明.constructor === 女兒小花.constructor // ture

那咱們用了找爸爸屬性,因此小明和小花的爸爸是同一個爸爸~

如今咱們再仔細看一下剛剛打印出來的小明。

敲黑板。

goFishing:ƒ (fis)
name:"小明"
__proto__:{
    cook:ƒ ()
    constructor:ƒ 爸爸(name)
    __proto__:Object
}

仔細看,constructor在哪裏~
大聲告訴我在哪裏~
在__proto__裏面對吧。
因此這個找爸爸的屬性是從爸爸那裏帶過來的,是爸爸告訴你怎麼找爸爸,而且沒有實際教會你怎麼找爸爸,是直接調用爸爸的獨門絕技找的爸爸~

狂敲黑板!

如今咱們再來往下科普一下其餘的幾個數據類型,再研究其原型。

它是 JavaScript 語言的第七種數據類型,前六種是:undefined、null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)
還有ES6 引入了一種新的原始數據類型Symbol,表示獨一無二的值。

咱們如今先來玩一下數字。

var 數字 = 12;
// 他是否有爸爸呢?
console.log(數字.__proto__)
// 跟着我敲敲看。
var 數字1 = new Number(12)
數字 == 數字1 // true
數字 === 數字1 // false

在打印數字的proto的時候,瞧咱們看到了什麼!
Number!
這就是他爸爸!

最後談一下繼承的方法吧。

es6:

Class 能夠經過 extends關鍵字實現繼承,這比 ES5 的經過修改原型鏈實現繼承,要清晰和方便不少。
子類必須在constructor方法中調用 super方法,不然新建實例時會 報錯。這是由於子類 沒有本身的this對象,而是 繼承父類的this對象,而後對其進行加工。若是不調用super方法,子類就 得不到this對象。

es5:

方法一:

子.prototype = new 爸爸()

新建一個爸爸做爲孩子的獨門絕技~
可是要想爲兒子新增屬性和方法,必需要在new 爸爸()這樣的語句以後執行,不能放到構造器中……
來自原型對象的引用屬性是全部實例共享的,建立子類實例時,沒法向父類構造函數傳參

方法二:

function 兒子(name){
 父親.call(this);
 this.name = name || 'Tom';
}

可是這樣的話,每一個兒子都要綁定爸爸的實例函數的副本,影響性能

方法三:

兒子.prototype = Object.create(爸爸.prototype)
創造一個新爸爸的獨門絕技來當兒子的獨門絕技~

其實方法有不少,我就不一一舉例了。

ECMAScript 繼承機制實現

若是對文章有什麼間接,歡迎悄悄告訴我~ =333333=
麼麼噠~上面我還寫了數字和數字1,猜猜看我下一章寫的是啥~~~

相關文章
相關標籤/搜索