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

資訊專(zhuān)欄INFORMATION COLUMN

深入理解 JavaScript 中的 class

Vicky / 1074人閱讀

摘要:在規(guī)范中,引入了的概念。使用中的聲明一個(gè)類(lèi),是非常簡(jiǎn)單的事。中面向?qū)ο髮?shí)例化的背后原理,實(shí)際上就是原型對(duì)象。與區(qū)別理解上述原理后,還需要注意與屬性的區(qū)別。實(shí)際上,在中,類(lèi)繼承的本質(zhì)依舊是原型對(duì)象。

在 ES6 規(guī)范中,引入了 class 的概念。使得 JS 開(kāi)發(fā)者終于告別了,直接使用原型對(duì)象模仿面向?qū)ο笾械念?lèi)和類(lèi)繼承時(shí)代。

但是JS 中并沒(méi)有一個(gè)真正的 class 原始類(lèi)型, class 僅僅只是對(duì)原型對(duì)象運(yùn)用語(yǔ)法糖。所以,只有理解如何使用原型對(duì)象實(shí)現(xiàn)類(lèi)和類(lèi)繼承,才能真正地用好 class

ES6:class

通過(guò)類(lèi)來(lái)創(chuàng)建對(duì)象,使得開(kāi)發(fā)者不必寫(xiě)重復(fù)的代碼,以達(dá)到代碼復(fù)用的目的。它基于的邏輯是,兩個(gè)或多個(gè)對(duì)象的結(jié)構(gòu)功能類(lèi)似,可以抽象出一個(gè)模板,依照模板復(fù)制出多個(gè)相似的對(duì)象。就像自行車(chē)制造商一遍一遍地復(fù)用相同的藍(lán)圖來(lái)制造大量的自行車(chē)。

使用 ES6 中的 class 聲明一個(gè)類(lèi),是非常簡(jiǎn)單的事。它的語(yǔ)法如下:

class Person {
  constructor(name){
    this.name = name
  }

  hello(){
    console.log("Hello, my name is " + this.name + ".");
  }
}

var xiaoMing = new Person("xiaoMing");
xiaoMing.hello() // Hello, my name is xiaoMing.

xiaoMing 是通過(guò)類(lèi) Person 實(shí)例化出來(lái)的對(duì)象。對(duì)象 xiaoMing 是按照類(lèi) Person 這個(gè)模板,實(shí)例化出來(lái)的對(duì)象。實(shí)例化出來(lái)的對(duì)象擁有類(lèi)預(yù)先訂制好的結(jié)構(gòu)和功能。

ES6 的語(yǔ)法很簡(jiǎn)單,但是在實(shí)例化的背后,究竟是什么在起作用呢?

class 實(shí)例化的背后原理

使用 class 的語(yǔ)法,讓開(kāi)發(fā)者告別了使用 prototype 模仿面向?qū)ο蟮臅r(shí)代。但是,class 并不是 ES6 引入的全新概念,它的原理依舊是原型繼承。

typeof class == "function"

通過(guò)類(lèi)型判斷,我們可以得知,class 的并不是什么全新的數(shù)據(jù)類(lèi)型,它實(shí)際只是 function (或者說(shuō) object)。

class Person {
  // ...
}

typeof Person // function

為了更加直觀地了解 Person 的實(shí)質(zhì),可以將它在控制臺(tái)打印出來(lái),如下。

Person 的屬性并不多,除去用 [[...]] 包起來(lái)的內(nèi)置屬性外,大部分屬性根據(jù)名字就能明白它的作用。需要我們重點(diǎn)關(guān)注的是 prototype__proto__ 兩個(gè)屬性。

(關(guān)于 __proto__ 可以在本文的姊妹篇 找到答案)

實(shí)例化的原理: prototype

先來(lái)講講 prototype 屬性,它指向一個(gè)特殊性對(duì)象:原型對(duì)象

原型對(duì)象所以特殊,是因?yàn)樗鼡碛幸粋€(gè)普通對(duì)象沒(méi)有的能力:將它的屬性共享給其他對(duì)象。

在 ES6 規(guī)范 中,對(duì) 原型對(duì)象 是如下定義的:

object that provides shared properties for other objects

原型對(duì)象是如何將它的屬性分享給其他對(duì)象的呢?

這里使用 ES5 創(chuàng)建一個(gè)類(lèi),并將它實(shí)例化,來(lái)看看它的實(shí)質(zhì)。

function Person() {
  this.name = name
}

// 1. 首先給 Person.prototype 原型對(duì)象添加了 describe 方法 。
Person.prototype.describe = function(){
  console.log("Hello, my name is " + this.name + ".");
}

// 2. 實(shí)例化對(duì)象的 __proto__ 指向 Person.prototype
var jane = new Person("jane");
jane.__proto__ === Person.prototype;


// 3. 讀取 describe 方法時(shí),實(shí)際會(huì)沿著原型鏈查找到 Person.prototype 原型對(duì)象上。
jane.describe() // Hello, my name is jane.

上述使用 JS 模仿面向?qū)ο髮?shí)例化的背后,實(shí)際有三個(gè)步驟:

首先給 Person.prototype 屬性所指的原型對(duì)象上添加了一個(gè)方法 describe

在使用 new 關(guān)鍵字創(chuàng)建對(duì)象時(shí),會(huì)默認(rèn)給該對(duì)象添加一個(gè)原型屬性 __proto__,該屬性指向 Person.prototype 原型對(duì)象。

在讀取 describe 方法時(shí),首先會(huì)在 jane 對(duì)象查找該方法,但是 jane 對(duì)象并不直接擁有 describe 方法。所以會(huì)沿著原型鏈查找到 Person.prototype 原型對(duì)象上,最后返回該原型對(duì)象的 describe 方法。

JS 中面向?qū)ο髮?shí)例化的背后原理,實(shí)際上就是 原型對(duì)象

為了方便大家理解,從網(wǎng)上扒了一張的圖片,放到這來(lái)便于大家理解。

prototype__proto__ 區(qū)別

理解上述原理后,還需要注意 prototype__proto__ 屬性的區(qū)別。

__proto__ 所指的對(duì)象,真正將它的屬性分享給它所屬的對(duì)象。所有的對(duì)象都有 __proto__ 屬性,它是一個(gè)內(nèi)置屬性,被用于繼承。

prototype 是一個(gè)只屬于 function 的屬性。當(dāng)使用 new 方法調(diào)用該構(gòu)造函數(shù)的時(shí)候,它被用于構(gòu)建新對(duì)象的 __proto__。另外它不可寫(xiě),不可枚舉,不可配置。

( new Foo() ).__proto__ === Foo.prototype
( new Foo() ).prototype === undefined
class 定義屬性

當(dāng)我們使用 class 定義屬性(方法)的時(shí)候,實(shí)際上等于是在 class 的原型對(duì)象上定義屬性。

class Foo {
  constructor(){ /* constructor */  }

  describe(){ /* describe */  }
}

// 等價(jià)于
function Foo (){
  /* constructor */
}

Foo.prototype.describe = function(){  /* describe */  }

constructor 是一個(gè)比較特殊的屬性,它指向構(gòu)造函數(shù)(類(lèi))本身。可以通過(guò)以下代碼驗(yàn)證。

Foo.prototype.constructor === Foo // true
類(lèi)繼承

在傳統(tǒng)面向?qū)ο笾校?lèi)是可以繼承類(lèi)的。這樣子類(lèi)就可以復(fù)制父類(lèi)的方法,達(dá)到代碼復(fù)用的目的。

ES6 也提供了類(lèi)繼承的語(yǔ)法 extends,如下:

class Foo {
  constructor(who){
    this.me = who;
  }

  identify(){
    return "I am " + this.me;
  }
}


class Bar extends Foo {
  constructor(who){
    // super() 指的是調(diào)用父類(lèi)
    // 調(diào)用的同時(shí),會(huì)綁定 this 。
    // 如:Foo.call(this, who)
    super(who);
  }

  speak(){
    alert( "Hello, " + this.identify() + "." );
  }
}

var b1 = new Bar( "b1" );

b1.speak();

當(dāng)實(shí)例 b1 調(diào)用 speak 方法時(shí),b1 本身沒(méi)有 speak,所以會(huì)到 Bar.prototype 原型對(duì)象上查找,并且調(diào)用原型對(duì)象上的 speak 方法。調(diào)用 identify 方式時(shí),由于 this 指向的是 b1 對(duì)象。所以也會(huì)先在 b1 本身查找,然后沿著原型鏈,查找 Bar.prototype,最后在 Foo.prototype 原型對(duì)象上找到 identify 方法,然后調(diào)用。

實(shí)際上,在 JavaScript 中,類(lèi)繼承的本質(zhì)依舊是原型對(duì)象。

他們的關(guān)系如下圖所示:

參考文章

(ES6 規(guī)范)[http://www.ecma-international...

MDN Classes

You-Dont-Know-JS

JavaScript difference between proto and prototype

proto VS. prototype in JavaScript

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

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

相關(guān)文章

  • 深入理解ES6》筆記—— JavaScript中的類(lèi)class(9)

    摘要:新建一個(gè)類(lèi)該函數(shù)返回一個(gè)類(lèi)的實(shí)例給函數(shù)傳入通過(guò)立即調(diào)用類(lèi)構(gòu)造函數(shù)可以創(chuàng)建單例。派生類(lèi)是指繼承自其它類(lèi)的新類(lèi)。在構(gòu)造函數(shù)中訪(fǎng)問(wèn)之前要調(diào)用,負(fù)責(zé)初始化。在構(gòu)造函數(shù)中使用通常表示當(dāng)前的構(gòu)造函數(shù)名。 ES5中的近類(lèi)結(jié)構(gòu) ES5以及之前的版本,沒(méi)有類(lèi)的概念,但是聰明的JavaScript開(kāi)發(fā)者,為了實(shí)現(xiàn)面向?qū)ο螅瑒?chuàng)建了特殊的近類(lèi)結(jié)構(gòu)。 ES5中創(chuàng)建類(lèi)的方法:新建一個(gè)構(gòu)造函數(shù),定義一個(gè)方法并且賦值...

    gggggggbong 評(píng)論0 收藏0
  • 深入理解ES6》筆記—— JavaScript中的類(lèi)class(9)

    摘要:新建一個(gè)類(lèi)該函數(shù)返回一個(gè)類(lèi)的實(shí)例給函數(shù)傳入通過(guò)立即調(diào)用類(lèi)構(gòu)造函數(shù)可以創(chuàng)建單例。派生類(lèi)是指繼承自其它類(lèi)的新類(lèi)。在構(gòu)造函數(shù)中訪(fǎng)問(wèn)之前要調(diào)用,負(fù)責(zé)初始化。在構(gòu)造函數(shù)中使用通常表示當(dāng)前的構(gòu)造函數(shù)名。 ES5中的近類(lèi)結(jié)構(gòu) ES5以及之前的版本,沒(méi)有類(lèi)的概念,但是聰明的JavaScript開(kāi)發(fā)者,為了實(shí)現(xiàn)面向?qū)ο螅瑒?chuàng)建了特殊的近類(lèi)結(jié)構(gòu)。 ES5中創(chuàng)建類(lèi)的方法:新建一個(gè)構(gòu)造函數(shù),定義一個(gè)方法并且賦值...

    Jason 評(píng)論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說(shuō),阮老師已經(jīng)有一本關(guān)于的書(shū)了入門(mén),覺(jué)得看看這本書(shū)就足夠了。前端的異步解決方案之和異步編程模式在前端開(kāi)發(fā)過(guò)程中,顯得越來(lái)越重要。為了讓編程更美好,我們就需要引入來(lái)降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(shū)(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書(shū)的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評(píng)論0 收藏0
  • 深入理解 JavaScript 原型繼承

    摘要:下面輪到我們的主角原型繼承登場(chǎng)了,它從另一個(gè)角度解決了重用的問(wèn)題。原型繼承的原理原型對(duì)象中的由兩部分組成,普通屬性的集合,和原型屬性。原型繼承的實(shí)現(xiàn)在上面的例子中,通過(guò)直接修改了屬性值,實(shí)現(xiàn)了原型繼承。使用原型繼承,同樣可以達(dá)到重用的目的。 繼承的本質(zhì):重用 在探討 JavaScript 的原型繼承之前,先不妨想想為什么要繼承? 考慮一個(gè)場(chǎng)景,如果我們有兩個(gè)對(duì)象,它們一部分屬性相同,另...

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

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

0條評(píng)論

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