今天來分享繫結的例外,
除了那四個規則外還是有例外。
當你使用 bind
、call
、apply
並且傳入 null
、undefined
當作參數,此時就會轉變成套用預設繫結也就是全域變數。
function foo(){
console.log(this.a);
}
var a = 2;
foo.call(null);
而主要使用的情境大概就是當你不在意 this 的是什麼時,但是你想要傳遞其他參數就用 null
來佔空間,
但這並不會是一個完美無缺的解決方式,他還是有可能會造成一些第三方的函式出現一些 bug 而且妳會很難抓到。
那... 斗洗爹 (我該怎麼辦呢)?
書中提到作者本身會偏好的實務做法是會使用電腦網路(或是軍方)的專業術語建立一個 DMZ( demilitarized zone ) 物件,主要就是一個完全空的,並且無委派的物件(書上說之後會講xD)。
Google 了一下維基百科
DMZ(全稱Demilitarized zone,中文為「非軍事區」,或稱Perimeter network,即「邊界網路」、周邊網路[1]或「對外網路」)為一種網路架構的布置方案,常用的架設方案是在不信任的外部網路和可信任的內部網路外,建立一個面向外部網路的物理或邏輯子網路,該子網路能設定用於對外部網路的伺服器主機。
該方案可以使用在防火牆、路由器等區隔內外網的網路裝置。在一般比較低階的網路裝置,DMZ的功能只能以軟體設定的介面去設定並實作,實體的網路層相接,會與一般的LAN PORT相接共同管理。不過在一般比較高階的網路裝置,如高階的防火牆裝置,DMZ的功能除了軟體的介面的設定外,在實體的連接PORT除了一般的WAN PORT、LAN PORT外,還會有另外獨立的DMZ PORT,這樣可以方便網路管理人員在管理網段時,除了軟體介面上去設定WAN、LAN、DMZ等網段外,在實體的纜線連接(通常採用的是RJ45)時,也可以直接區分網段,更方便管理。
...
我們還是看範例好了 xDD
ø: 小寫的空集合數學符號 (Option+O)
如果你不喜歡也可以找其他的~
function foo(a,b){
console.log(`a: ${a}, b: ${b}`);
}
var ø = Object.create(null);
foo.apply(ø,[2,3]); // a: 2, b:3
var bar = foo.bind(ø, 2);
bar(3); // a: 2, b:3
基本上 DMZ 物件的名稱你喜歡就好,但是不要用一般會取的變數跟我說那是 DMZ 就好 xDD
除了功能上的好處,ø
在語義上還傳達了這個 this 是空的比 null 還清楚。
基本上就是字面上的意思,當你建立出對函式得間接參考也會套用到預設繫結。
如下面的範例
function foo(){
console.log(this.a);
}
var a = 2;
var x = {a: 3, foo:foo};
var y = {a:4};
x.foo(); // 3
(y.foo = x.foo)(); // 2 oh shit
另外如果是嚴格模式的話 this 就是 undefined
。
ES6 引進的箭頭函式大家應該都不陌生,不過他不適用這幾天講的四種規則xD
讓我們一起來看看吧~
function foo(){
return (a)=>{
console.log(this.a);
};
}
var obj = {
a:0;
};
var obj1= {
a:1;
};
var bar = foo.call(obj);
bar.call(obj1); // 0
主要原因是箭頭函式被呼叫時會從語彙捕捉到 foo()
的 this,所以 foo
已經被繫結到 obj
時,他也會一起連結到 obj
,而且他不會被覆寫。
以上是今天的內容
明天開始會分享物件~
你所不知道的 JS|範疇與 Closures,this 與物件原型 (You Don't Know JS: this & Object Prototypes))