《你不知道的JavaScript》 原型鏈訪問的坑

2021-09-09 05:56:41 字數 2948 閱讀 7880

本篇開始看下js物件原型[[prototype]]

js中的物件有一種特殊的內建屬性[[prototype]],其實就是對於其他物件的引用。幾乎所有的物件在建立時都[[prototype]]屬性都會被賦予乙個非空的值。

var obj =

console.

log(obj.a)

;// 2

var newobj = object.

create

(obj)

;console.

log(newobj.a)

;// 2

上例的newobj物件的[[prototype]]屬性指向obj物件。

當試圖引用物件的屬性時會觸發[[get]]操作,例如obj.anewobj.a。對於預設的[[get]]操作來說,第一步是檢查物件本身是否有這個屬性,如果有的話就使用它。如果物件本身沒有這個屬性,就需要使用到物件的內建屬性[[prototype]]了,[[get]]操作會訪問物件的[[prototype]]鏈,對於上例的newobj.a操作而言就是會繼續訪問其原型鏈上層的obj物件。

現在我們明白訪問物件的屬性時,會先查詢物件本身,如本身沒有對應屬性時,會向該物件的原型鏈上層物件查詢,找到則返回該屬性的值,如始終沒有找到,則返回undefined

那麼這個始終沒有找到的盡頭在哪?就在object.prototype。它是js中所有物件的源頭,object.prototype的再上一層也有,但是null了。

不光訪問物件的屬性可能會查詢其原型鏈,為物件屬性設定值時同樣也可能會查詢該物件的原型鏈。

通常為物件屬性設定值我們採用=賦值操作符來進行,當為物件obj的foo屬性設定值時:

obj.foo =

"bar"

;

// 1.

var parentobj =

;var obj = object.

create

(parentobj)

;obj.foo =5;

console.

log(obj.foo)

;// 5

// 2.

var parentobj =

;object.

defineproperty

(parentobj,

"foo",)

;var obj = object.

create

(parentobj)

;obj.foo =5;

console.

log(obj.foo)

;// 10 無法修改已有屬性或在obj物件上建立遮蔽屬性 非嚴格模式時忽略obj.foo = 5;操作,嚴格模式時直接報錯

// 3.

var parentobj =

,set

foo(val)

}parentobj.foo =10;

console.

log(parentobj.foo)

;// 40

var obj = object.

create

(parentobj)

;obj.foo =3;

console.

log(obj.foo)

;// 12 繼續呼叫原型鏈上層物件上 setter,

console.

log(obj.

hasownproperty

("foo"))

;// false 並且foo還不會被新增到obj物件上

如果希望在第2和第3種情況也能遮蔽foo屬性,就不能使用=賦值操作符,而應使用object.defineproperty()來向obj物件新增foo。

// 2.

var parentobj =

;object.

defineproperty

(parentobj,

"foo",)

;var obj = object.

create

(parentobj)

;object.

defineproperty

(obj,

"foo",)

console.

log(obj.foo)

;// 5 這回可以在obj物件建立遮蔽屬性foo了,值也為最新值 5

// 3.

var parentobj =

,set

foo(val)

}parentobj.foo =10;

console.

log(parentobj.foo)

;// 40

var obj = object.

create

(parentobj)

;object.

defineproperty

(obj,

"foo",)

console.

log(obj.foo)

;// 7

你看,所以如果確實想改,也是有辦法的,用object.defineproperty()就行。

你不知道的javascript(二)

1.詞法作用域 就是定義在詞法階段的作用域,作用域查詢會在找到第乙個匹配的識別符號時停止。在多層的巢狀作用域中可以定義同名的標識 符,這叫作 遮蔽效應 內部的識別符號 遮蔽 了外部的識別符號 拋開遮蔽效應,作用域查詢始終從 執行時所處的最內部作用域開始,逐級向外或者說向上進行,直到遇見第乙個匹配的識...

你不知道的JavaScript (上)

一 編譯的原理主要分為三個步驟 1 分詞 詞法分析 這個步驟主要是將字串分解成有意義的 2 解析 語法分析 陣列巢狀形成結構樹。3 生成 將結構樹轉化為 的過程。二 作用域 引擎主要進行搜尋查詢編譯等過程,分為左查詢lhs和右查詢rhs 編譯器主要是進行 的生成,語法分析。作用域主要是 確定訪問許可...

你不知道的JavaScript 筆記

作用域是什麼?作用域的兩種工作模式 詞法作用域和動態作用域 1.查詢 作用域查詢會在找到第乙個匹配識別符號停止 2.欺騙詞法 eval 修改作用域 with 建立新的作用域 後果 導致js引擎在靜態分析時停止優化,導致效能下降 遵循最小授權原則 1.隱藏內部實現 2.規避衝突 3.立即執行函式 ii...