成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

深入理解 js 之繼承與原型鏈

xingqiba / 1283人閱讀

摘要:原型鏈與繼承當(dāng)談到繼承時(shí),只有一種結(jié)構(gòu)對(duì)象。如果對(duì)該圖不怎么理解,不要著急,繼續(xù)往下看基于原型鏈的繼承對(duì)象是動(dòng)態(tài)的屬性包指其自己的屬性。當(dāng)使用操作符來(lái)作用這個(gè)函數(shù)時(shí),它就可以被稱(chēng)為構(gòu)造方法構(gòu)造函數(shù)。

原型鏈與繼承

當(dāng)談到繼承時(shí),JavaScript 只有一種結(jié)構(gòu):對(duì)象。每個(gè)實(shí)例對(duì)象(object )都有一個(gè)私有屬性(稱(chēng)之為proto)指向它的原型對(duì)象(prototype)。該原型對(duì)象也有一個(gè)自己的原型對(duì)象(proto) ,層層向上直到一個(gè)對(duì)象的原型對(duì)象為 null。根據(jù)定義,null 沒(méi)有原型,并作為這個(gè)原型鏈中的最后一個(gè)環(huán)節(jié)。

新建函數(shù),并創(chuàng)建對(duì)象

function Car() {
    this.name = "BMW"
    this.price = 95800
}
let carBMW = new Car()

這時(shí)我們的腦海里應(yīng)該有這樣一張圖:

或許你跟我初次接觸一樣。如果對(duì)該圖不怎么理解,不要著急,繼續(xù)往下看?。?!

基于原型鏈的繼承

JavaScript 對(duì)象是動(dòng)態(tài)的屬性“包”(指其自己的屬性)。JavaScript 對(duì)象有一個(gè)指向一個(gè)原型對(duì)象的鏈。當(dāng)試圖訪(fǎng)問(wèn)一個(gè)對(duì)象的屬性時(shí),它不僅僅在該對(duì)象上搜尋,還會(huì)搜尋該對(duì)象的原型,以及該對(duì)象的原型的原型,依次層層向上搜索,直到找到一個(gè)名字匹配的屬性或到達(dá)原型鏈的末尾。

從 ECMAScript 6 開(kāi)始,[[Prototype]] 可以通過(guò)Object.getPrototypeOf()和Object.setPrototypeOf()訪(fǎng)問(wèn)器來(lái)訪(fǎng)問(wèn)。這個(gè)等同于 JavaScript 的非標(biāo)準(zhǔn)但許多瀏覽器實(shí)現(xiàn)的屬性 __proto__。

接著上述代碼

console.log(carBMW)  // *Car {name: "BMW", price: 95800}*

在 Car() 函數(shù)的原型上定義屬性

Car.prototype.price = 200000
Car.prototype.speed = 300

console.log(carBMW.__proto__)  // {price: 200000, speed: 300, constructor: ?}
console.log(carBMW.__proto__.__proto__ == Object.prototype)  // true
console.log(carBMW.__proto__.__proto__.__proto__) // null

綜合上述代碼,可以給出如下原型鏈

{name: "BMW", price: 95800} ---> {price: 200000, speed: 300, constructor: ?} ---> Object.prototype ---> null

繼續(xù)寫(xiě)代碼

console.log(carBMW.name)   // BMW
// name 為 carBMW 自身的屬性

console.log(carBMW.price)  // 95800
// price 為 carBMW 自身的屬性,原型上也有一個(gè)"price"屬性,但是不會(huì)被訪(fǎng)問(wèn)到,這種情況稱(chēng)為"屬性遮蔽 (property shadowing)"

console.log(carBMW.speed)  // 300
// speed 不是 carBMW 自身的屬性,但是 speed 位于該原型鏈上,因此我們依然可以取到該值

// 當(dāng)然如果你試著訪(fǎng)問(wèn)一個(gè)不存在原型鏈上的屬性時(shí),這時(shí)候會(huì)給你返回一個(gè)undefined

當(dāng)我們給對(duì)象設(shè)置一個(gè)屬性時(shí),創(chuàng)建的屬性稱(chēng)為對(duì)象的自有屬性。

函數(shù)的繼承與其他的屬性繼承沒(méi)有差別,包括上面的“屬性遮蔽”(這種情況相當(dāng)于其他語(yǔ)言的方法重寫(xiě))。

當(dāng)繼承的函數(shù)被調(diào)用時(shí),this 指向的是當(dāng)前繼承的對(duì)象,而不是繼承的函數(shù)所在的原型對(duì)象。
let car = {
  price: 95800,
  getPrice: function(){
    return this.a
  }
}

console.log(car.getPrice()); // 95800
// 當(dāng)調(diào)用 car.getPrice() 時(shí),"this"指向了car.

let bmw = Object.create(car);
// bmw 是一個(gè)繼承自 car 的對(duì)象

bmw.price = 400000; // 創(chuàng)建 bmw 的自身屬性 price
console.log(bmw.getPrice()); // 400000
// 調(diào)用 bmw.getPrice() 時(shí), "this"指向 bmw. 
// 又因?yàn)?bmw 繼承 car 的 getPrice 函數(shù)
// 此時(shí)的"this.price" 即 bmw.a,即 price 的自身屬性 "price" 

雖然有點(diǎn)繞,細(xì)讀之后邏輯并不是很復(fù)雜

多種方法創(chuàng)建對(duì)象 基于字面量創(chuàng)建對(duì)象
也就是根據(jù)相應(yīng)的語(yǔ)法結(jié)構(gòu)直接進(jìn)行創(chuàng)建
let car = {
  price: 95800,
  getPrice: function(){
    return this.a
  }
}
// car 為一個(gè)對(duì)象,因此相應(yīng)的原型鏈應(yīng)該如下
// car ---> Object.prototype ---> null

let cars = ["BMW","Audi","WulingHongguang"]
// cars 為一個(gè)數(shù)組對(duì)象,相應(yīng)的原型鏈應(yīng)該如下
// cars ---> Array.prototype ---> Object.prototype ---> null
基于構(gòu)造函數(shù)創(chuàng)建對(duì)象
在 JavaScript 中,構(gòu)造器其實(shí)就是一個(gè)普通的函數(shù)。當(dāng)使用 new 操作符 來(lái)作用這個(gè)函數(shù)時(shí),它就可以被稱(chēng)為構(gòu)造方法(構(gòu)造函數(shù))。
function Car() {
    this.name = "BMW"
    this.price = 95800
}
Car.prototype.speed = 300
let car = new Car()
// 可以知道,car 的自身屬性 {name: "BMW", price: 95800}, 位于原型鏈上的屬性有 speed .
基于Object.create()創(chuàng)建對(duì)象
ECMAScript 5 中引入了一個(gè)新方法:Object.create()??梢哉{(diào)用這個(gè)方法來(lái)創(chuàng)建一個(gè)新對(duì)象。新對(duì)象的原型就是調(diào)用 create 方法時(shí)傳入的第一個(gè)參數(shù)
var car = {price: 10000}; 
// car ---> Object.prototype ---> null

var carBMW = Object.create(car);
// carBMW ---> car ---> Object.prototype ---> null
console.log(carBMW.price); // 10000 (繼承而來(lái))
基于 Class 關(guān)鍵字創(chuàng)建對(duì)象
ECMAScript6 引入了一套新的關(guān)鍵字用來(lái)實(shí)現(xiàn) class。實(shí)質(zhì)上還是語(yǔ)法糖,底層原理依舊不變
class Point {
     constructor(x, y) {
        this.x = x;
        this.y = y;
     }
     toString() {
       return "(" + this.x + ", " + this.y + ")";
     }
}
var point = new Point(2, 3);
point.toString() // (2, 3)
point.hasOwnProperty("x") // true
point.hasOwnProperty("y") // true
point.hasOwnProperty("toString") // false
point.__proto__.hasOwnProperty("toString") // true

以上代碼中,x和y都是實(shí)例對(duì)象point自身的屬性(因?yàn)槎x在this變量上),所以hasOwnProperty方法返回true,而toString是原型對(duì)象的屬性(因?yàn)槎x在Point類(lèi)上),所以hasOwnProperty方法返回false。這些都與ES5的行為保持一致。

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

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

相關(guān)文章

  • 深入學(xué)習(xí)js——原型原型

    摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們?cè)趺幢硎緦?shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開(kāi)篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門(mén)基于原型的語(yǔ)言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來(lái)相對(duì)簡(jiǎn)單,而是因?yàn)閺囊婚_(kāi)始B...

    FingerLiu 評(píng)論0 收藏0
  • 深入學(xué)習(xí)js——原型原型

    摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們?cè)趺幢硎緦?shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開(kāi)篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門(mén)基于原型的語(yǔ)言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來(lái)相對(duì)簡(jiǎn)單,而是因?yàn)閺囊婚_(kāi)始B...

    xialong 評(píng)論0 收藏0
  • JavaScript深入各種繼承

    摘要:通常有這兩種繼承方式接口繼承和實(shí)現(xiàn)繼承。理解繼承的工作是通過(guò)調(diào)用函數(shù)實(shí)現(xiàn)的,所以是寄生,將繼承工作寄托給別人做,自己只是做增強(qiáng)工作。適用基于某個(gè)對(duì)象或某些信息來(lái)創(chuàng)建對(duì)象,而不考慮自定義類(lèi)型和構(gòu)造函數(shù)。 一、繼承的概念 繼承,是面向?qū)ο笳Z(yǔ)言的一個(gè)重要概念。通常有這兩種繼承方式:接口繼承和實(shí)現(xiàn)繼承。接口繼承只繼承方法簽名,而實(shí)現(xiàn)繼承則繼承實(shí)際的方法。 《JS高程》里提到:由于函數(shù)沒(méi)有簽名,...

    tomlingtm 評(píng)論0 收藏0
  • 深入理解JavaScript

    摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對(duì)于解釋型語(yǔ)言例如來(lái)說(shuō),通過(guò)詞法分析語(yǔ)法分析語(yǔ)法樹(shù),就可以開(kāi)始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫(xiě)在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...

    myeveryheart 評(píng)論0 收藏0
  • 面向?qū)ο蟮?JavaScript

    摘要:是完全的面向?qū)ο笳Z(yǔ)言,它們通過(guò)類(lèi)的形式組織函數(shù)和變量,使之不能脫離對(duì)象存在。而在基于原型的面向?qū)ο蠓绞街?,?duì)象則是依靠構(gòu)造器利用原型構(gòu)造出來(lái)的。 JavaScript 函數(shù)式腳本語(yǔ)言特性以及其看似隨意的編寫(xiě)風(fēng)格,導(dǎo)致長(zhǎng)期以來(lái)人們對(duì)這一門(mén)語(yǔ)言的誤解,即認(rèn)為 JavaScript 不是一門(mén)面向?qū)ο蟮恼Z(yǔ)言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從?duì)語(yǔ)言感悟的角度闡述為什...

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

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

0條評(píng)論

閱讀需要支付1元查看
<