亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

講清楚之 javascript 對(duì)象繼承

Jonathan Shieber / 1797人閱讀

摘要:中的繼承并不是明確規(guī)定的,而是通過(guò)模仿實(shí)現(xiàn)的。繼承中的繼承又稱(chēng)模擬類(lèi)繼承。將函數(shù)抽離到全局對(duì)象中,函數(shù)內(nèi)部直接通過(guò)作用域鏈查找函數(shù)。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質(zhì)區(qū)別是屬性查找方式的不同。

這一節(jié)梳理對(duì)象的繼承。

我們主要使用繼承來(lái)實(shí)現(xiàn)代碼的抽象和代碼的復(fù)用,在應(yīng)用層實(shí)現(xiàn)功能的封裝。

javascript 的對(duì)象繼承方式真的是百花齊放,屬性繼承、原型繼承、call/aplly繼承、原型鏈繼承、對(duì)象繼承、構(gòu)造函數(shù)繼承、組合繼承、類(lèi)繼承... 十幾種,每一種都細(xì)講需要花很多時(shí)間,這里大致梳理常用的幾種。 javascript 中的繼承并不是明確規(guī)定的,而是通過(guò)模仿實(shí)現(xiàn)的。下面我們簡(jiǎn)單梳理幾種有代表性的繼承。

原型繼承

ECMAScript 5 中引入了一個(gè)新方法: Object.create??梢哉{(diào)用這個(gè)方法來(lái)創(chuàng)建一個(gè)新對(duì)象。新對(duì)象的原型就是調(diào)用 create 方法時(shí)傳入的參數(shù):

let too = {
    a: 1
}
let foo = Object.create(too)
console.log(foo.a) // 1

通過(guò)使用Object.create方法, 對(duì)象 too 會(huì)被自動(dòng)加入到 foo 的原型上。我們可以手動(dòng)模擬實(shí)現(xiàn)一個(gè)Object.create相同功能的函數(shù):

let too = {
    a: 1
}
function create (prot) {
    let o = function () {}
    o.prototype = prot
    return new o()
}
let foo = create(too)
console.log(foo.a) // 1

或者用更簡(jiǎn)單直白的方式來(lái)寫(xiě):

function Foo() {}
Foo.prototype = {
    a: 1
}

let too = new Foo()
console.log(too.a) // 1

原型繼承是基于函數(shù)的prototype屬性

原型鏈的繼承
function Foo (id) {
    this.a = 1234
    this.b = id || 0
}
Foo.prototype.showData = function () {
    console.log(`${this.a}, id: ${this.b}`)
}
function Too (id) {
    Foo.apply(this, arguments)
}
Too.prototype = new Foo()
let bar = new Too(999)
bar.showData() // 1234, id: 999

上面構(gòu)造函數(shù)TOO 通過(guò)重新指定prototype屬性,指向了構(gòu)造函數(shù)Foo的一個(gè)實(shí)例,然后在Too構(gòu)造函數(shù)中調(diào)用Foo的構(gòu)造函數(shù),從而完成對(duì)構(gòu)造函數(shù)Foo功能的繼承。實(shí)例bar 通過(guò)屬性__proto__來(lái)訪(fǎng)問(wèn)原型鏈上的共享屬性和方法。

class繼承

javascript 中的 class繼承又稱(chēng)模擬類(lèi)繼承。ES6中正式引入了 class 關(guān)鍵字來(lái)實(shí)現(xiàn)類(lèi)語(yǔ)言方式創(chuàng)建對(duì)象。從此我們也可以使用抽象類(lèi)的方式來(lái)實(shí)現(xiàn)繼承。

// 父類(lèi)
class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
// 子類(lèi)
class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength); // 調(diào)用父對(duì)象的搞糟函數(shù)
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);

在JavaScript中沒(méi)有類(lèi)的概念,只有對(duì)象。雖然我們使用class關(guān)鍵字,這讓 JavaScript 看起來(lái)似乎是擁有了”類(lèi)”,可表面看到的不一定是本質(zhì),class只是語(yǔ)法糖,實(shí)質(zhì)還是原型鏈那一套。因此,JavaScript中的繼承只是對(duì)象與對(duì)象之間的繼承。反觀(guān)繼承的本質(zhì),繼承便是讓子類(lèi)擁有父類(lèi)的一些屬性和方法,在JavaScript中便是讓一個(gè)對(duì)象擁有另一個(gè)對(duì)象的屬性和方法。

繼承的實(shí)現(xiàn)是有很多種,這里不一一列舉。需要注意的是 javascript 引擎在原型鏈上查找屬性是比較耗時(shí)的,對(duì)性能有副作用。與此同時(shí)我們遍歷對(duì)象時(shí),原型上的屬性也會(huì)被枚舉出來(lái)。要識(shí)別屬性是在對(duì)象上還是從原型上繼承的,我們可以使用對(duì)象上的hasOwnProperty方法:

let foo = {
    a: 1
}
foo.hasOwnProperty("a") // true
foo.hasOwnProperty("toString") // false

使用hasOwnProperty方法檢測(cè)屬性是否直接存在于該對(duì)象上并不會(huì)遍歷原型鏈。

javascript 支持的是實(shí)現(xiàn)繼承,不支持接口繼承,實(shí)現(xiàn)繼承主要依賴(lài)的是原型鏈。

思考

前面我們講到的基本是 javascript 怎么實(shí)現(xiàn)面向?qū)ο缶幊痰囊恍┲R(shí)點(diǎn)。

不從概念來(lái)講,簡(jiǎn)單來(lái)說(shuō)當(dāng)我們有屬性和方法需要被重復(fù)使用,或者屬性需要被多個(gè)對(duì)象共享時(shí)就需要去考慮繼承的問(wèn)題。在函數(shù)層面,大家通常的做法是使用作用域鏈來(lái)實(shí)現(xiàn)內(nèi)層作用域?qū)ν鈱幼饔糜驅(qū)傩曰蚝瘮?shù)的共享訪(fǎng)問(wèn)。舉個(gè)栗子吧~~

function car (userName) {
    let color = "red"
    let wheelNumber = 4
    let user = userName
    let driving = function () {
        console.log(`${user} 的汽車(chē),${wheelNumber}個(gè)輪子滾啊滾...`)
    }
    let stop = function () {
        console.log(`${user} 的汽車(chē),${wheelNumber}個(gè)輪子滾不動(dòng)了,嘎。。。`)
    }
    return {
        driving: driving,
        stop: stop
    }
}
var maruko = car("小丸子")
maruko.driving() // 小丸子 的汽車(chē),4個(gè)輪子滾啊滾...
maruko.stop() // 小丸子 的汽車(chē),4個(gè)輪子滾不動(dòng)了,嘎。。。

var nobita = car("大雄")
nobita.driving() // 大雄 的汽車(chē),4個(gè)輪子滾啊滾...
nobita.stop() // 大雄 的汽車(chē),4個(gè)輪子滾不動(dòng)了,嘎。。。

這。。。什么鬼。是不是有種似曾相識(shí)的感覺(jué),這其實(shí)就是經(jīng)典的閉包 ,jquery 年代很多插件 js 庫(kù)都采用這種方式去封裝獨(dú)立的功能。說(shuō)閉包也是繼承是不是有點(diǎn)勉強(qiáng),但是 javascript 里函數(shù)也是對(duì)象,閉包利用函數(shù)的作用域鏈來(lái)訪(fǎng)問(wèn)上層作用域的屬性和函數(shù)。當(dāng)然像閉包這樣不使用this去實(shí)現(xiàn)私有屬性比較麻煩, 閉包只適合單實(shí)例的場(chǎng)景。再舉一個(gè)栗子:

function GoToBed (name) {
    console.log(`${name}, 睡覺(jué)了...`)
}
function maruko () {
    let name = "小丸子"
    function dinner () {
        console.log(`${name}, 吃完晚餐`)
        GoToBed(name)
    }
    dinner()
}

function nobita () {
    let name = "大雄"
    function homework () {
        console.log(`${name}, 做完作業(yè)`)
        GoToBed(name)
    }
    homework()
}

maruko()
nobita()

// 小丸子, 吃完晚餐
// 小丸子, 睡覺(jué)了...
// 大雄, 做完作業(yè)
// 大雄, 睡覺(jué)了...

像上面栗子中這樣,以面向過(guò)程的方式將公共方法抽離到上層作用域的用法比較常見(jiàn), 至少我很長(zhǎng)時(shí)間都是這么干的。將GoToBed函數(shù)抽離到全局對(duì)象中,函數(shù)marukonobita 內(nèi)部直接通過(guò)作用域鏈查找GoToBed函數(shù)。這種松散結(jié)構(gòu)的代碼塊組織其實(shí)跟上面閉包含義是差不多的。

所以依據(jù)作用域鏈來(lái)進(jìn)行公共屬性、方法的管理嚴(yán)格意義上不能算是繼承, 只能算是 javascript 面向過(guò)程的一種代碼抽象分解的方式,一種編程范式。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質(zhì)區(qū)別是屬性查找方式的不同。

全局對(duì)象 window 形成一個(gè)閉合上下文,如果我們將整個(gè) window 對(duì)象假設(shè)為一個(gè)全局函數(shù),所有創(chuàng)建的局部函數(shù)都是該函數(shù)的內(nèi)部函數(shù)。當(dāng)我們使用這個(gè)假設(shè)時(shí)很多問(wèn)題就要清晰多了,全局函數(shù)在頁(yè)面被關(guān)閉前是一直存在的,且在存活期間為內(nèi)嵌函數(shù)提供執(zhí)行環(huán)境,所有內(nèi)嵌函數(shù)都共享對(duì)全局環(huán)境的讀寫(xiě)權(quán)限。

這種函數(shù)調(diào)用時(shí)命令式的,函數(shù)組織是嵌套的,使用閉包(函數(shù)嵌套)的方式來(lái)組織代碼流是無(wú)模式的一種常態(tài)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/107939.html

相關(guān)文章

  • 講清楚之 javascript原形

    摘要:構(gòu)造函數(shù)和實(shí)例都通過(guò)屬性指向了原形。代碼示例是構(gòu)造函數(shù)的實(shí)例的屬性與的屬性保存的值相等,即他們指向同一個(gè)對(duì)象原形。 講清楚之javascript原型 標(biāo)簽: javascript javascript 中原形是一個(gè)比較難于理解的概念。javascript 權(quán)威指南在原形這一章也花了大量的篇幅進(jìn)行介紹,也許你已經(jīng)讀過(guò)javascript 權(quán)威指南,或者已經(jīng)是讀第N篇了,然而這篇文章的目...

    高勝山 評(píng)論0 收藏0
  • 講清楚之 javascript中的this

    摘要:講清楚之中的這一節(jié)來(lái)探討。所以當(dāng)函數(shù)作為構(gòu)造函數(shù)調(diào)用,則函數(shù)內(nèi)部的綁定到該函數(shù)上。在通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象時(shí),對(duì)象內(nèi)部的也同樣指向該實(shí)例對(duì)象。 講清楚之 javascript中的this 這一節(jié)來(lái)探討this。 在 javascript 中 this 也是一個(gè)神的存在,相對(duì)于 java 等語(yǔ)言在編譯階段確定,而在 javascript 中, this 是動(dòng)態(tài)綁定,也就是在運(yùn)行期綁定的。...

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

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

0條評(píng)論

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