摘要:構(gòu)造函數(shù)創(chuàng)建一個(gè)對象上邊這個(gè)例子,我們通過構(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è)對象
function Person() { } var person = new Person(); person.name = "zhangsan"; console.log(person.name) // zhangsan
上邊這個(gè)例子,我們通過構(gòu)造函數(shù)創(chuàng)建了一個(gè)實(shí)例,從這個(gè)實(shí)例到他的原型到最后得object,他們之間得關(guān)系,就形成了一個(gè)原型鏈
prototype __proto__ 和 constructor首先上邊這個(gè)例子里邊,我們聲明了一個(gè)構(gòu)造函數(shù),在后再這個(gè)構(gòu)造函數(shù)里邊有一個(gè)prototype的屬性。
注意這個(gè)prototype屬性,是只有函數(shù)才會(huì)有屬性
Person.prototype.name = "zhangsan"; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // zhangsan console.log(person2.name) // zhangsan
首先我們看到再函數(shù)的prototype屬性上邊我們定義了一個(gè)name屬性,然后通過new創(chuàng)建了兩個(gè)實(shí)例,
然后通過調(diào)用實(shí)例的name屬性,也可以拿到構(gòu)造函數(shù)prototype屬性上邊的name屬性,
那么這個(gè)prototype到底是有什么用處呢,
prototype
這個(gè)只有函數(shù)才會(huì)有的屬性,他其實(shí)指向了一個(gè)對象,而這個(gè)對象就是調(diào)用了構(gòu)造函數(shù)創(chuàng)建實(shí)例的原型
,可以理解成是person1,person2在創(chuàng)建的時(shí)候從他們的原型把原型的屬性委托給了person1和person2
這里為什么不叫他繼承,因?yàn)槔^承的定義是賦值一個(gè)一模一樣的實(shí)例出來,但是js里邊并不會(huì)復(fù)制
proto
這個(gè)__proto__屬性是每個(gè)對象實(shí)例都會(huì)有的一個(gè)屬性,這個(gè)屬性也會(huì)指向該對象的原型
function Person() {} var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true
可以粘貼一下代碼到瀏覽器打印一下person1 可以看到__proto__這個(gè)屬性
constructor
constructor這個(gè)屬性之前我也叫他構(gòu)造函數(shù),叫習(xí)慣了,因?yàn)槊總€(gè)原型上邊都會(huì)有一個(gè)constructor這個(gè)屬性,指向其相關(guān)的構(gòu)造函數(shù)
function Person() {} console.log(Person === Person.prototype.constructor); // true原型鏈的查找機(jī)制
首先在你創(chuàng)建一個(gè)實(shí)例的時(shí)候,你去讀取實(shí)例上邊的屬性,他會(huì)首先再實(shí)例上邊去查找,如果找不到,那么就去這個(gè)實(shí)例的原型上邊去找,如果還是找不到,就會(huì)去原型的原型上邊去找,直到最后找到Object對象,當(dāng)然object對象也是有原型的 就是null
記得之前的時(shí)候,遇到過這么一個(gè)問題就是typeof null的 時(shí)候?yàn)槭裁词莻€(gè)object,記得當(dāng)時(shí)得到的答案是說null是一個(gè)對象的空指針,從現(xiàn)在來看null打印object是有原因的
那么還是查找不到的話會(huì)怎么樣的,不要慌(.?ー?), 他會(huì)返給你一個(gè)undefined(.?ー?)
最后拉一張圖
圖中藍(lán)色的這個(gè)鏈狀的結(jié)構(gòu)的線就是原型鏈
js的作用域首先什么叫做作用域
作用域是指程序源代碼中定義變量的區(qū)域。作用域規(guī)定了如何查找變量,也就是確定當(dāng)前執(zhí)行代碼對變量的訪問權(quán)限。
JavaScript 采用詞法作用域(lexical scoping),也就是靜態(tài)作用域。
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
網(wǎng)上拿來的例子,直接說過程
在執(zhí)行階段執(zhí)行foo的時(shí)候,直接在foo尋找value ,因?yàn)閖s是靜態(tài)作用域,所以在foo里邊沒有找到的時(shí)候,直接去上一層找,最后結(jié)果是1
var value = 1; function bar() { var value = 2; console.log(value); } bar();
同理這段代碼bar里邊有value 直接打印2
那么再看一個(gè)例子
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope();
這個(gè)例子會(huì)打印出什么,大家可以猜一猜
結(jié)果就是local scope
那么為什么上邊的第一段代碼里邊同樣是在函數(shù)里邊執(zhí)行另一個(gè)函數(shù),但是他不會(huì)用第一個(gè)函數(shù)里邊的變量呢,
原因就是js是靜態(tài)作用域,js執(zhí)行一個(gè)函數(shù)的時(shí)候分為兩個(gè)階段,首先會(huì)解析一變,這個(gè)時(shí)候確定了詞法作用域和this指向,屬性聲明等,然后才是函數(shù)執(zhí)行階段
函數(shù)的作用域是基于函數(shù)創(chuàng)建的位置的,所以第一段代碼和下邊這段代碼的函數(shù)作用域是不想同的
說到這里的時(shí)候,我在上文中提到了執(zhí)行上下文和函數(shù)執(zhí)行的過程,之前在我得另一篇博客里邊寫道過,有興趣的可以去看下 js的堆棧隊(duì)列
以上是我對js原型鏈和作用域的一些認(rèn)識(shí),有不足的希望指正,之前在博客園寫的。搬過來的
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/105461.html
摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們怎么表示實(shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來相對簡單,而是因?yàn)閺囊婚_始B...
摘要:我們用一張圖表示構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系好了構(gòu)造函數(shù)和實(shí)例原型之間的關(guān)系我們已經(jīng)梳理清楚了,那我們怎么表示實(shí)例與實(shí)例原型,也就是或者和之間的關(guān)系呢。 開篇: 在Brendan Eich大神為JavaScript設(shè)計(jì)面向?qū)ο笙到y(tǒng)的時(shí)候,借鑒了Self 和Smalltalk這兩門基于原型的語言,之所以選擇基于原型的面向?qū)ο笙到y(tǒng),并不是因?yàn)闀r(shí)間匆忙,它設(shè)計(jì)起來相對簡單,而是因?yàn)閺囊婚_始B...
摘要:原型鏈與繼承當(dāng)談到繼承時(shí),只有一種結(jié)構(gòu)對象。如果對該圖不怎么理解,不要著急,繼續(xù)往下看基于原型鏈的繼承對象是動(dòng)態(tài)的屬性包指其自己的屬性。當(dāng)使用操作符來作用這個(gè)函數(shù)時(shí),它就可以被稱為構(gòu)造方法構(gòu)造函數(shù)。 原型鏈與繼承 當(dāng)談到繼承時(shí),JavaScript 只有一種結(jié)構(gòu):對象。每個(gè)實(shí)例對象(object )都有一個(gè)私有屬性(稱之為proto)指向它的原型對象(prototype)。該原型對象也...
摘要:原文發(fā)自我的博客易企秀招聘啦首先我們先來回顧以下中出現(xiàn)的原型繼承原型繼承自如果我們要在上查詢一個(gè)定義在的屬性會(huì)先在上查找如果沒有查到那么會(huì)順著原型鏈去查找所以以下判別式均為如果我們做如下操作原型鏈并沒有被訪問一個(gè)新的會(huì)被加入到的屬性中去新的 原文發(fā)自我的博客 xiaoyu2er.github.io 易企秀招聘啦! JavaScript Prototypal Inheritance 首先...
摘要:深入之繼承的多種方式和優(yōu)缺點(diǎn)深入系列第十五篇,講解各種繼承方式和優(yōu)缺點(diǎn)。對于解釋型語言例如來說,通過詞法分析語法分析語法樹,就可以開始解釋執(zhí)行了。 JavaScript深入之繼承的多種方式和優(yōu)缺點(diǎn) JavaScript深入系列第十五篇,講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 寫在前面 本文講解JavaScript各種繼承方式和優(yōu)缺點(diǎn)。 但是注意: 這篇文章更像是筆記,哎,再讓我...
閱讀 2838·2021-11-19 09:40
閱讀 5701·2021-09-27 14:10
閱讀 2170·2021-09-04 16:45
閱讀 1580·2021-07-25 21:37
閱讀 3059·2019-08-30 10:57
閱讀 3060·2019-08-28 17:59
閱讀 1116·2019-08-26 13:46
閱讀 1478·2019-08-26 13:27