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

資訊專(zhuān)欄INFORMATION COLUMN

JS中原型和原型鏈深入理解

Alex / 2697人閱讀

摘要:如果要理清原型和原型鏈的關(guān)系,首先要明確一下幾個(gè)概念中的所有東西都是對(duì)象,函數(shù)也是對(duì)象而且是一種特殊的對(duì)象中所有的東西都由衍生而來(lái)即所有東西原型鏈的終點(diǎn)指向?qū)ο蠖加幸粋€(gè)隱藏的屬性,他指向創(chuàng)建它的構(gòu)造函數(shù)的原型,但是有一個(gè)例外,指向的是。

首先要搞明白幾個(gè)概念:

函數(shù)(function)

函數(shù)對(duì)象(function object)

本地對(duì)象(native object)

內(nèi)置對(duì)象(build-in object)

宿主對(duì)象(host object)

函數(shù)
function foo(){
    
}
var foo = function(){
    
}

前者為函數(shù)聲明,后者為函數(shù)表達(dá)式。typeof foo
的結(jié)果都是function。

函數(shù)對(duì)象

函數(shù)就是對(duì)象,代表函數(shù)的對(duì)象就是函數(shù)對(duì)象

官方定義, 在Javascript中,每一個(gè)函數(shù)實(shí)際上都是一個(gè)函數(shù)對(duì)象.

JavaScript代碼中定義函數(shù),或者調(diào)用Function創(chuàng)建函數(shù)時(shí),最終都會(huì)以類(lèi)似這樣的形式調(diào)用Function函數(shù):var newFun = new Function(funArgs, funBody)

其實(shí)也就是說(shuō),我們定義的函數(shù),語(yǔ)法上,都稱(chēng)為函數(shù)對(duì)象,看我們?nèi)绾稳ナ褂?。如果我們單純的把它?dāng)成一個(gè)函數(shù)使用,那么它就是函數(shù),如果我們通過(guò)他來(lái)實(shí)例化出對(duì)象來(lái)使用,那么它就可以當(dāng)成一個(gè)函數(shù)對(duì)象來(lái)使用,在面向?qū)ο蟮姆懂犂锩?,函?shù)對(duì)象類(lèi)似于類(lèi)的概念。

var foo = new function(){
    
}
typeof foo // object

或者

function Foo (){
    
}
var foo = new Foo();

typeof foo // object

上面,我們所建立的對(duì)象

本地對(duì)象
ECMA-262 把本地對(duì)象(native object)定義為“獨(dú)立于宿主環(huán)境的 ECMAScript 實(shí)現(xiàn)提供的對(duì)象”。簡(jiǎn)單來(lái)說(shuō),本地對(duì)象就是 ECMA-262 定義的類(lèi)(引用類(lèi)型)。它們包括:
Object,Function,Array,String,Boolean,Number
Date,RegExp,Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError.

我們不能被他們起的名字是本地對(duì)象,就把他們理解成對(duì)象(雖然是事實(shí)上,它就是一個(gè)對(duì)象,因?yàn)镴S中萬(wàn)物皆為對(duì)象),通過(guò)

typeof(Object)
typeof(Array)
typeof(Date)
typeof(RegExp)
typeof(Math)

返回的結(jié)果都是function

也就是說(shuō)其實(shí)這些本地對(duì)象(類(lèi))是通過(guò)function建立起來(lái)的,

function Object(){
    
}
function Array(){
    
}
...

可以看出Object原本就是一個(gè)函數(shù),通過(guò)new Object()之后實(shí)例化后,創(chuàng)建對(duì)象。類(lèi)似于JAVA中的類(lèi)。

內(nèi)置對(duì)象
ECMA-262 把內(nèi)置對(duì)象(built-in object)定義為“由 ECMAScript 實(shí)現(xiàn)提供的、獨(dú)立于宿主環(huán)境的所有對(duì)象,在 ECMAScript 程序開(kāi)始執(zhí)行時(shí)出現(xiàn)”。這意味著開(kāi)發(fā)者不必明確實(shí)例化內(nèi)置對(duì)象,它已被實(shí)例化了。ECMA-262 只定義了兩個(gè)內(nèi)置對(duì)象,即 Global 和 Math (它們也是本地對(duì)象,根據(jù)定義,每個(gè)內(nèi)置對(duì)象都是本地對(duì)象)。

理清楚了這幾個(gè)概念,有助于理解我們下面要講述的原型和原型鏈。

prototype

prototype屬性是每一個(gè)函數(shù)都具有的屬性,但是不是一個(gè)對(duì)象都具有的屬性。比如

function Foo(){
    
}

var foo = new Foo();

其中Foo中有prototype屬性,而foo沒(méi)有。但是foo中的隱含的__proto__屬性指向Foo.prototype。

foo.__proto__ === Foo.prototype

為什么會(huì)存在prototype屬性?

Javascript里面所有的數(shù)據(jù)類(lèi)型都是對(duì)象,為了使JavaScript實(shí)現(xiàn)面向?qū)ο蟮乃枷耄捅仨氁軌驅(qū)崿F(xiàn)‘繼承’使所有的對(duì)象連接起來(lái)。而如何實(shí)現(xiàn)繼承呢?JavaScript采用了類(lèi)似C++,java的方式,通過(guò)new的方式來(lái)實(shí)現(xiàn)實(shí)例。

舉個(gè)例子,child1,child2都是Mother的孩子,且是雙胞胎。(雖然不是很好,但是還是很能說(shuō)明問(wèn)題的)

function Mother(name){
    this.name = name;
    this.father = "baba";
}
var child1 = new Mother("huahua");
var child2 = new Mother("huahua");

如果有一天,發(fā)現(xiàn)孩子的父親其實(shí)是Baba,那么就要修改每一個(gè)孩子的father屬性。

child1.father ="Baba";
console.log(child2.father) // baba

也就是說(shuō)修改了其中一個(gè)孩子的father屬性不會(huì)影響到下一個(gè),屬性的值無(wú)法共享。

正是這個(gè)原因才提出來(lái)prototype屬性,把需要共享的屬性放到構(gòu)造函數(shù)也就是父類(lèi)的實(shí)例中去。

__proto__

__proto__屬性是每一個(gè)對(duì)象以及函數(shù)都隱含的一個(gè)屬性。對(duì)于每一個(gè)含有__proto__屬性,他所指向的是創(chuàng)建他的構(gòu)造函數(shù)的prototype。原型鏈就是通過(guò)這個(gè)屬性構(gòu)件的。

想像一下,如果一個(gè)函數(shù)對(duì)象(也稱(chēng)為構(gòu)造函數(shù))a的prototype是另一個(gè)函數(shù)對(duì)象b構(gòu)建出的實(shí)例,a的實(shí)例就可以通過(guò)__proto__與b的原型鏈起來(lái)。而b的原型其實(shí)就是Object的實(shí)例,所以a的實(shí)例對(duì)象,就可以通過(guò)原型鏈和object的prototype鏈接起來(lái)。

function a(){
    
}
function b(){
    
}
var b1 = new b();
a.prototype = b1;
var a1 = new a();
console.log(a1.__proto__===b1);//true
console.log(a1.__proto__.__proto__===b.prototype) //true
console.log(a1.__proto__.__proto__.__proto__===Object.prototype) //true

如果要理清原型和原型鏈的關(guān)系,首先要明確一下幾個(gè)概念:
1.JS中的所有東西都是對(duì)象,函數(shù)也是對(duì)象, 而且是一種特殊的對(duì)象

2.JS中所有的東西都由Object衍生而來(lái), 即所有東西原型鏈的終點(diǎn)指向Object.prototype

3.JS對(duì)象都有一個(gè)隱藏的__proto__屬性,他指向創(chuàng)建它的構(gòu)造函數(shù)的原型,但是有一個(gè)例外,Object.prototype.__proto__指向的是null。

4.JS中構(gòu)造函數(shù)和實(shí)例(對(duì)象)之間的微妙關(guān)系

構(gòu)造函數(shù)通過(guò)定義prototype來(lái)約定其實(shí)例的規(guī)格, 再通過(guò) new 來(lái)構(gòu)造出實(shí)例,他們的作用就是生產(chǎn)對(duì)象.

function Foo(){
    
}
var foo = new Foo();
foo其實(shí)是通過(guò)Foo.prototype來(lái)生成實(shí)例的。

構(gòu)造函數(shù)本身又是方法(Function)的實(shí)例, 因此也可以查到它的__proto__(原型鏈)

function Foo(){
    
}
等價(jià)于
var Foo= new Function();

而Function實(shí)際上是

function Function(){
    Native Code
}
也就是等價(jià)于
var Function= new Function();

所以說(shuō)Function是通過(guò)自己創(chuàng)建出來(lái)的。正常情況下對(duì)象的__proto__是指向創(chuàng)建它的構(gòu)造函數(shù)的prototype的.所以Function的__proto__指向的Function.prototype

Object 實(shí)際上也是通過(guò)Function創(chuàng)建出來(lái)的

typeof(Object)//function
所以,
function Object(){
    Native Code
}
等價(jià)于
var Object = new Function();

那么Object的__proto__指向的是Function.prototype,也即是

Object.__proto__ === Function.prototype //true

下面再來(lái)看Function.prototype的__proto__指向哪里

因?yàn)镴S中所有的東西都是對(duì)象,那么,F(xiàn)unction.prototype 也是對(duì)象,既然是對(duì)象,那么Function.prototype肯定是通過(guò)Object創(chuàng)建出來(lái)的,所以,

 Function.prototype.__proto__ === Object.prototype //true

綜上所述,F(xiàn)unction和Object的原型以及原型鏈的關(guān)系可以歸納為下圖。

對(duì)于單個(gè)的對(duì)象實(shí)例,如果通過(guò)Object創(chuàng)建,

var obj = new Object();

那么它的原型和原型鏈的關(guān)系如下圖

如果通過(guò)函數(shù)對(duì)象來(lái)創(chuàng)建,

function Foo(){
    
}
var foo = new Foo();

那么它的原型和原型鏈的關(guān)系如下圖

那JavaScript的整體的原型和原型鏈中的關(guān)系就很清晰了,如下圖所示

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

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

相關(guān)文章

  • js深入(一)從原型理解原型

    摘要:構(gòu)造函數(shù)創(chuàng)建一個(gè)對(duì)象上邊這個(gè)例子,我們通過(guò)構(gòu)造函數(shù)創(chuàng)建了一個(gè)實(shí)例,從這個(gè)實(shí)例到他的原型到最后得,他們之間得關(guān)系,就形成了一個(gè)原型鏈和首先上邊這個(gè)例子里邊,我們聲明了一個(gè)構(gòu)造函數(shù),在后再這個(gè)構(gòu)造函數(shù)里邊有一個(gè)的屬性。 構(gòu)造函數(shù)創(chuàng)建一個(gè)對(duì)象 function Person() { } var person = new Person(); person.name = zhangsan; c...

    馬忠志 評(píng)論0 收藏0
  • 深入理解 js 之繼承與原型

    摘要:原型鏈與繼承當(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ì)象也...

    xingqiba 評(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...

    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
  • 通過(guò)類(lèi)型繼承深入理解原型繼承

    摘要:上圖中的在原型繼承稱(chēng)作構(gòu)造器。構(gòu)造器就是一個(gè)普通的函數(shù),但是將操作符用到構(gòu)造器上時(shí),它會(huì)執(zhí)行一個(gè)叫的過(guò)程。從第條可以看到,構(gòu)造器生成的對(duì)象的屬性會(huì)指向構(gòu)造器的值,這就是我們構(gòu)造原型鏈的關(guān)鍵。 基于類(lèi)的繼承是大多數(shù)人所熟悉的,也是比較容易理解的。當(dāng)我們形成類(lèi)型繼承的思維定勢(shì)后,再次接觸原型繼承可能會(huì)覺(jué)得有些奇怪并難以理解。你更可能會(huì)吐槽,原型繼承根本就不能叫做繼承,一點(diǎn)都不面向?qū)ο?。本?..

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

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

0條評(píng)論

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