国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深入淺出面向?qū)ο蠛驮汀靖拍钇?】—— 原型鏈和繼承

levinit / 3275人閱讀

摘要:由一個(gè)問題引發(fā)的思考這個(gè)方法是從哪兒蹦出來的首先我們要清楚數(shù)組也是對(duì)象,而且是對(duì)象的實(shí)例也就是說,下面兩種形式是完全等價(jià)的只不過是一種字面量的寫法,在深入淺出面向?qū)ο蠛驮透拍钇恼吕?,我們提到過類會(huì)有一個(gè)屬性,而這個(gè)類的實(shí)例可以通過屬性訪

1.由一個(gè)問題引發(fā)的思考
    let arr1 = [1, 2, 3]
    let arr2 = [4, 5, 6]
    arr1.concat(arr2) // [1, 2, 3, 4, 5, 6]
concat這個(gè)方法是從哪兒蹦出來的??
    首先我們要清楚 數(shù)組也是對(duì)象,而且是Array對(duì)象的實(shí)例
    
    console.log(arr1 instanceof Array) // true

    也就是說,下面兩種形式是完全等價(jià)的
    let arr1 = [1, 2, 3]
    let arr2 = new Array(1, 2, 3)

    只不過[1,2,3]是一種字面量的寫法

ok,在深入淺出面向?qū)ο蠛驮汀靖拍钇?】文章里,我們提到過

類會(huì)有一個(gè)prototype屬性,而這個(gè)類的實(shí)例可以通過__proto__屬性訪問類的prototype屬性

既然arr1是Array對(duì)象的實(shí)例,那么arr1自然可以通過其__proto__屬性訪問到其類Array的屬性
只要Array的prototype里有concat()這個(gè)方法,那么arr1自然能用

    console.log(arr1.__proto__ === Array.prototype) // true
2.第二個(gè)問題 arr1.valueOf(),valueOf從哪兒來的?
按照第一個(gè)問題的解決思路,valueOf應(yīng)該是Array的prototype屬性里的
但是在Array的prototype屬性里并沒有找到valueOf方法


但是我們又看到了Array的prototype里竟然也有__proto__屬性,并且指向Object,在這里我們找到了valueOf

這是為什么呢?

現(xiàn)在我們需要知道的是Array是Object的實(shí)例

    console.log(Array instanceof Object) // true
好了,現(xiàn)在我們知道了
1.arr1 是 Array 的實(shí)例
2.Array 是 Object 的實(shí)例

當(dāng)arr1找不到valueOf時(shí),會(huì)通過其自身的__proto__屬性去找Array的prototype,看看里面有沒有
如果Array的prototype里沒有的話,接下來會(huì)通過Array的prototype里的__proto__屬性去找Object的prototype,看看里面有沒有

而反觀arr1尋找concat時(shí),因?yàn)橹苯泳驮贏rray的prototype里找到了,所以不會(huì)再去通過__proto__尋找Object的prototype里有沒有
我們把這個(gè)過程抽象化表達(dá)

當(dāng)一個(gè)實(shí)例調(diào)用一個(gè)方法時(shí)

如果實(shí)例本身沒有這個(gè)方法,那么這個(gè)實(shí)例會(huì)通過自身的__proto__屬性去訪問其類的prototype屬性

如果該實(shí)例的類的prototype屬性也沒有,那么會(huì)通過該類prototype屬性里的__proto__屬性去訪問該類的類的prototype屬性

若還沒有找到,則以此類推,直到找到該方法或者父級(jí)類的prototype內(nèi)的__proto__為null時(shí)為止

這個(gè)不斷通過__proto__屬性和prototype屬性尋找的過程,叫做原型鏈

3.自己實(shí)現(xiàn)繼承 3.1 什么是繼承
繼承是指一個(gè)對(duì)象直接使用另一對(duì)象的屬性和方法
3.2 繼承的目的
繼承的目的其實(shí)就是省代碼,什么意思呢?

假設(shè)你現(xiàn)在是js設(shè)計(jì)師,你已經(jīng)設(shè)計(jì)了Object對(duì)象
現(xiàn)在你需要基于Object對(duì)象再設(shè)計(jì)一個(gè)Array對(duì)象
并且Array對(duì)象可以直接使用Object對(duì)象的屬性和方法
這個(gè)時(shí)候你肯定希望能夠通過一種方式能直接讓Array對(duì)象使用Object對(duì)象的屬性和方法
而不是把Object對(duì)象的屬性和方法重新寫到Array里去,這樣做太累了

而這種方式就叫繼承
3.3 實(shí)現(xiàn)繼承的要點(diǎn)
由繼承的定義,我們可知,實(shí)現(xiàn)繼承必須滿足兩個(gè)條件
1.得到一個(gè)類的屬性
2.得到一個(gè)類的方法
第一步:我們先定義兩個(gè)類
// 第一個(gè)類
function People(name, age) {
    this.name = name
    this.age = age
}

People.prototype = {
    printName: function () {
        console.log(this.name)
    }
}

// 第二個(gè)類
function Male(sex) {
    this.sex = sex
}

Male.prototype = {
    printSex: function () {
        console.log(this.sex)
    }
}
第二步:讓Male的每個(gè)實(shí)例都獲取到People的屬性
function Male(sex, name, age) {
    // 注意Male的實(shí)例在這里就是this
    // 所以我們要讓this獲取到People的屬性即可
    // 實(shí)現(xiàn)方式——讓People的this被替換成Male的this,且讓People被直接調(diào)用
    People.bind(this)(name, age)
    this.sex = sex
}

console.log(new Male("man", "bruce", "16")) // {name: "bruce", age: "16", sex: "man"}
第三步:讓Male的每個(gè)實(shí)例都獲取到People的方法

Object.create()

    // 例子
    let a = Object.create({"zxz": 1})
    console.log(a.__proto__) // {zxz: 1}
    // Object.create() 方法會(huì)返回一個(gè)對(duì)象,這個(gè)對(duì)象擁有被指定的原型
    // 且這個(gè)對(duì)象可通過自身的__proto__屬性訪問這個(gè)原型
    Male.prototype = Object.create(People.prototype)
    // 這一步結(jié)束后,Male的實(shí)例就可以通過原型鏈擁有People的方法

    // 接著,我們才能對(duì)Male自己要新增的方法進(jìn)行添加,否則會(huì)被覆蓋掉

    Male.prototype.printSex = function () {
        console.log(this.sex)
    }

    console.log((new Male("man", "bruce", "16")).__proto__.__proto__ === People.prototype)
第四步:注意constructor屬性
我們都知道constructor屬性指向其類
當(dāng)我們完成第三步后
需要注意的是

console.log(Male.prototype.constructor === People.prototype.constructor) // true

因?yàn)閳?zhí)行了Object.create()的原因,此時(shí)Male原型上的constructor被指定成People了
現(xiàn)在需要我們手動(dòng)賦值將其更改

Male.prototype.constructor = Male
現(xiàn)在,我們可以把上述步驟統(tǒng)一起來
function People(name, age) {
    this.name = name
    this.age = age
}

People.prototype = {
    printName: function () {
        console.log(this.name)
    }
}

function Male(sex, name, age) {
    People.bind(this)(name, age)
    this.sex = sex
}

Male.prototype = Object.create(People.prototype)
Male.prototype.constructor = Male
Male.prototype.printSex = function () {
    console.log(this.sex)
}
3.4 把繼承獲取方法的關(guān)鍵步驟封裝起來
function inherit(fatherObject, childObject) {
    let _prototype = Object.create(fatherObject.prototype);
    _prototype.constructor = childObject;
    childObject.prototype = _prototype;
}
3.5 完整代碼
function inherit(fatherObject, childObject) {
    let _prototype = Object.create(fatherObject.prototype);
    _prototype.constructor = childObject;
    childObject.prototype = _prototype;
}

function People(name, age) {
    this.name = name
    this.age = age
}

People.prototype = {
    printName: function () {
        console.log(this.name)
    }
}

function Male(sex, name, age) {
    People.bind(this)(name, age)
    this.sex = sex
}

inherit(People, Male)
Male.prototype.printSex = function () {
    console.log(this.sex)
}

let bruce = new Male("man", "bruce", 16)
4.實(shí)現(xiàn)繼承的其它方法
function People(name, age) {
    this.name = name
    this.age = age
}

People.prototype.sayName = function () {
    console.log(this.name)
}

function Student(name, age, score) {
    People.call(this, name, age)
    this.score = score
}

function create(prototypeObj) {
    let empty = function () {}
    empty.prototype = prototypeObj
    return new empty()
    // return值如下
    // {
    //     __proto__:prototypeObj
    // }
}

Student.prototype = create(People.prototype)

Student.prototype.work = function () {
    console.log("work")
}
5.hasOwnProperty
當(dāng)Male的實(shí)例繼承了Male的方法和People的屬性和方法后,如何分辨某個(gè)屬性或方法是自己的還是通過原型鏈繼承來的呢?
這就要用到 hasOwnProperty
該方法可以判斷一個(gè)對(duì)象是否包含自定義屬性而不是原型鏈上的屬性
并且會(huì)忽略掉那些從原型鏈上繼承到的屬性

console.log(bruce.hasOwnProperty("age")) // true
console.log(bruce.hasOwnProperty("printSex")) // false

因?yàn)閜rintSex方法是bruce實(shí)例通過原型鏈從Male類的原型上獲取的,因此會(huì)被hasOwnProperty忽略

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/92945.html

相關(guān)文章

  • 深入javascript——原型繼承

    摘要:在使用原型鏈實(shí)現(xiàn)繼承時(shí)有一些需要我們注意的地方注意繼承后的變化。在了解原型鏈時(shí),不要忽略掉在末端還有默認(rèn)的對(duì)象,這也是我們能在所有對(duì)象中使用等對(duì)象內(nèi)置方法的原因。 在上一篇post中,介紹了原型的概念,了解到在javascript中構(gòu)造函數(shù)、原型對(duì)象、實(shí)例三個(gè)好基友之間的關(guān)系:每一個(gè)構(gòu)造函數(shù)都有一個(gè)守護(hù)神——原型對(duì)象,原型對(duì)象心里面也存著一個(gè)構(gòu)造函數(shù)的位置,兩情相悅,而實(shí)例呢卻又...

    UCloud 評(píng)論0 收藏0
  • 詳解javascript的類

    摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨校愂菍?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語言,一...

    hufeng 評(píng)論0 收藏0
  • 詳解javascript的類

    摘要:原文地址詳解的類博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類又該怎么定義呢在面向?qū)ο缶幊讨?,類是?duì)象的模板,定義了同一組對(duì)象又稱實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語言,一...

    marek 評(píng)論0 收藏0
  • 剖析JS的原型繼承

    摘要:接下來我們來聊一下的原型鏈繼承和類。組合繼承為了復(fù)用方法,我們使用組合繼承的方式,即利用構(gòu)造函數(shù)繼承屬性,利用原型鏈繼承方法,融合它們的優(yōu)點(diǎn),避免缺陷,成為中最常用的繼承。 JavaScript是一門面向?qū)ο蟮脑O(shè)計(jì)語言,在JS里除了null和undefined,其余一切皆為對(duì)象。其中Array/Function/Date/RegExp是Object對(duì)象的特殊實(shí)例實(shí)現(xiàn),Boolean/N...

    darkerXi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<