成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript 中的原型原來是這樣的

yuanxin / 2719人閱讀

摘要:而在原型對象中默認有一個屬性存儲了構(gòu)造函數(shù)的地址引用也就是指向了構(gòu)造函數(shù)。原型鏈的頂端是是所有對象的祖宗,的值為。但是上面的代碼把構(gòu)造函數(shù)和原型分開寫了。

什么是原型
原型其實就是一個特殊的對象,在聲明函數(shù)的時候自動創(chuàng)建的。

比如,我們現(xiàn)在聲明一個構(gòu)造函數(shù) A ,除了會申請保存函數(shù)的內(nèi)存空間,還會額外申請一個內(nèi)存空間,用于存儲構(gòu)造函數(shù) A 的原型對象。所有函數(shù)中(Function.prototype.bind 除外)默認都有一個 prototype 的屬性,它保存了函數(shù)的原型對象的地址(引用)(也就是它指向了原型對象)。
而在原型對象中默認有一個 constructor 屬性存儲了構(gòu)造函數(shù)的地址(引用)(也就是 constructor 指向了構(gòu)造函數(shù))。如果不理解上面所說的,那我們看下面的圖:

瀏覽器控制臺中:

_ _proto_ _prototype
剛開始接觸原型的時候這兩個東西很容易就搞混了。

先記住以下兩點,就很容易就區(qū)分了:

prototype 是函數(shù)中才有的屬性

__proto__ 是所有對象都有的屬性

我們已經(jīng)知道了函數(shù)中的 prototype 屬性指向的是它的原型對象,那么對象中的 __proto__ 代表什么?

一般情況下,對象中的 __proto__ 屬性是指向它的構(gòu)造函數(shù)的原型對象的,即和構(gòu)造函數(shù)中的 prototype 屬性所指向的對象是同一個對象。

用一段簡單的代碼:

function A() {}
var a = new A()

上圖看著不夠簡便,我們簡化一下:

還有一點,__proto__ 不是一個規(guī)范屬性,ie(除了 ie10) 不支持。對應(yīng)的標準屬性是 [[Prototype]] ,但是這個屬性我們沒法直接訪問到。開發(fā)者盡量不要用這種方式去訪問,因為操作不慎會改變這個對象的繼承原型鏈。

在使用 Object.create(參數(shù)) 方式創(chuàng)建對象時,對象的 __proto__ 屬性指向的是傳入的參數(shù)。

原型鏈
由于 __proto__ 是所有對象都具有的屬性,而 __proto__ 本身指向的原型(函數(shù).prototype)也是一個對象,它也有 __proto__ 屬性。所以這樣會形成由 __proto__對象原型連起來的鏈條。這就是原型鏈。原型鏈的頂端是 Object.prototype(Object 是所有對象的祖宗) ,Object.prototype.__proto__的值為 null 。

還是看之前的代碼:

function A() {}
var a = new A()

它的原型鏈如下:

構(gòu)造函數(shù) A 其實也是一個對象。所有函數(shù)都是由 Function 函數(shù)構(gòu)造的。(聲明函數(shù) function A() {} 等價于 var A = new Function()) 。所以所有函數(shù)的 __proto__ 指向的都是 Function.prototype 。更新上圖:

Function 也是一個函數(shù),它的 __proto__ 指向的也是 Functon.prototypeFuntion.__proto__ === Function.prototype。繼更新上圖:

Object 同樣是一個函數(shù),所以 Object.__proto__ === Function.prototype

到了這里,我們應(yīng)該可以看懂下面這張圖了:

原型的作用
當 JS 引擎查找對象屬性時,先查找對象本身是否存在該屬性,如果不存在,會在對象的 __proto__ 里找,還找不到就會沿著原型鏈一直找到原型鏈頂端(Object.prototype) 直到找到屬性為止,最后在原型鏈頂端都沒找到就返回 undefined

由于上面的機制,原型的作用就很明顯了——共享屬性,節(jié)省內(nèi)存空間。

function Animal() {
    this.name = "動物"
    this.eat = function() {
        console.log("在吃···")
    }
}
var a1 = new Animal()
var a2 = new Animal()

console.log(a1.eat === a2.eat)  // false
// 每個對象的 eat 方法不是同一個,但方法類容一樣,浪費內(nèi)存

使用 原型解決:

function Animal(name) {
    this.name = "動物"
}
Animal.prototype.eat = function() {
    console.log("吃")
}

var a1 = new Animal()
var a2 = new Animal()

console.log(a1.eat === a2.eat)  //true
// a1.eat 和 a2.eat 都同一個方法(Animal.prototype.eat)

原型非常適合封裝共享的方法。但是上面的代碼把構(gòu)造函數(shù)和原型分開寫了。封裝不到位。使用動態(tài)類型模式解決。

function Animal() {
    this.name = "動物"
    
    /*
      判斷 this.eat 是不是 函數(shù)類型,
      如果不是,則表示是第一次創(chuàng)建對象或者調(diào)用 Animal 函數(shù),
      會將 eat 添加到原型中去。
      如果是,則表示原型中存在了 eat 方法,不需要再添加。
    */
    if(typeof this.eat !== "function") {
        Animal.prototype.eat = function() {
            console.log("吃")
        }
    }
}

var a = new Animal()
a.eat()

原型基于之前的共享屬性和方法,是實現(xiàn) JS 中繼承的基礎(chǔ)。

與原型有關(guān)的方法 hasOwnProperty()

通過之前的學習,我們知道了去訪問一個對象的屬性時,會在原型鏈上查找。所以我們并不知道這個屬性來自哪里。

hasOwnProperty() 方法返回一個布爾值,可以判斷一個屬性是否來自對象本身。

function Animal() {}
Animal.prototype.name = "動物"
var a = new Animal()
a.age = 3

console.log(a.hasOwnProperty("name"))  // false
console.log(a.hasOwnProperty("age")  // true
in 操作符
in 操作符用返回一個布爾值,用來判斷一個屬性能否在對象上找到。在對象的原型鏈上找到也返回 true。
function Animal() {}
Animal.prototype.name = "動物"
var a = new Animal()
a.age = 3

console.log("name" in a)  // true
console.log("age" in  a)  // true
console.log("sex" in  a)  // false
總結(jié)

原型就是一個對象,聲明函數(shù)就會創(chuàng)建原型對象

prototype 只存在于函數(shù)中

所有對象都有一個 __proto__ 屬性,它指向?qū)ο蟮臉?gòu)造函數(shù)的原型

原型 也是對象,也有 __proto__ 屬性,__proto__ 將對象和原型連接起來,形成原型鏈

Object.prototype 是原型鏈的頂端

訪問對象的屬性會沿著對象的原型鏈找下去

原型可以共享屬性和方法,是繼承的基礎(chǔ)

閱讀原文

參考資料:

https://juejin.im/post/5835853f570c35005e413b19

https://blog.csdn.net/u012468376/article/details/53121081

https://juejin.im/book/5bdc715fe51d454e755f75ef/section/5bed40d951882545f73004f6

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109097.html

相關(guān)文章

  • JS面向?qū)ο蠖?this/原型鏈/new原理

    摘要:情況沒有明確作用對象的情況下,通常為全局對象例如函數(shù)的回調(diào)函數(shù),它的就是全局對象。正因如此,機器可以作為這類對象的標志,即面向?qū)ο笳Z言中類的概念。所以機器又被稱為構(gòu)造函數(shù)。原型鏈也就是繼承鏈。 JS面向?qū)ο蠖?this/原型鏈/new原理 阮一峰JavaScript教程:面向?qū)ο缶幊?阮一峰JavaScript教程:實例對象與 new 命令 阮一峰JavaScript教程:this 關(guān)...

    anRui 評論0 收藏0
  • 我來重新學習 javascript 面向?qū)ο螅╬art 2)

    摘要:先來說其實構(gòu)造函數(shù)也有,原型對象有,實例有也有,或者更加籠統(tǒng)的說,所有對象都是有的。構(gòu)造函數(shù)的原型對象上的會指向構(gòu)造函數(shù)。由于屬性是可以變更的,所以未必真的指向?qū)ο蟮臉?gòu)造函數(shù),只是一個提示。 續(xù)上一集內(nèi)容,通過構(gòu)造函數(shù)的方式,成功地更新了生產(chǎn)技術(shù),老板笑呵呵,工人少奔波,只是問題總比辦法多,又遇到一個新問題,就是會造成一些資源的重復和浪費,那么經(jīng)過工程師們的智慧交流,他們產(chǎn)生了一個新技...

    silvertheo 評論0 收藏0
  • 徹底理解Javascript原型鏈與繼承

    摘要:在節(jié)中,我們學習到了通過構(gòu)造函數(shù)創(chuàng)建對象的三個重要步驟,其中的一步是把構(gòu)造函數(shù)的對象設(shè)置為創(chuàng)建對象的原型。利用而不是直接用創(chuàng)建一個實例對象的目的是,減少一次調(diào)用父構(gòu)造函數(shù)的執(zhí)行。 JavaScript語言不像面向?qū)ο蟮木幊陶Z言中有類的概念,所以也就沒有類之間直接的繼承,JavaScript中只有對象,使用函數(shù)模擬類,基于對象之間的原型鏈來實現(xiàn)繼承關(guān)系,ES6的語法中新增了class關(guān)鍵...

    ziwenxie 評論0 收藏0
  • javascript高級程序設(shè)計》第六章 讀書筆記 之 javascript對象幾種創(chuàng)建方式

    摘要:三種使用構(gòu)造函數(shù)創(chuàng)建對象的方法和的作用都是在某個特殊對象的作用域中調(diào)用函數(shù)。這種方式還支持向構(gòu)造函數(shù)傳遞參數(shù)。叫法上把函數(shù)叫做構(gòu)造函數(shù),其他無區(qū)別適用情境可以在特殊的情況下用來為對象創(chuàng)建構(gòu)造函數(shù)。 一、工廠模式 工廠模式:使用字面量和object構(gòu)造函數(shù)會有很多重復代碼,在此基礎(chǔ)上改進showImg(https://segmentfault.com/img/bVbmKxb?w=456&...

    xiaotianyi 評論0 收藏0
  • 讀《javaScript高級程序設(shè)計-第6章》之封裝類

    摘要:創(chuàng)建構(gòu)造函數(shù)后,其原型對象默認只會取得屬性至于其他的方法都是從繼承來的。上圖展示了構(gòu)造函數(shù)的原型對象和現(xiàn)有的兩個實例之間的關(guān)系。所有原生的引用類型都在其構(gòu)造函數(shù)的原型上定義了方法。 第6章我一共寫了3篇總結(jié),下面是相關(guān)鏈接:讀《javaScript高級程序設(shè)計-第6章》之理解對象讀《javaScript高級程序設(shè)計-第6章》之繼承 工廠模式 所謂的工廠模式就是,把創(chuàng)建具體對象的過程抽象...

    seal_de 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<