摘要:但是如果某個(gè)函數(shù)確實(shí)使用了,那默認(rèn)綁定規(guī)則會把綁定到全局對象在瀏覽器中這個(gè)對象是,這將導(dǎo)致不可預(yù)計(jì)的后果比如修改全局對象。實(shí)際上并不存在所謂的構(gòu)造函數(shù),只有對于函數(shù)的構(gòu)造調(diào)用。使用來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會自動(dòng)執(zhí)行下面的操作。
1. 默認(rèn)綁定this 實(shí)際上是在函數(shù)被調(diào)用時(shí)發(fā)生的綁定,它指向什么完全取決于函數(shù)在哪里被調(diào)用(也就是函數(shù)的調(diào)用方法)。
獨(dú)立函數(shù)調(diào)用時(shí),應(yīng)用 this 的默認(rèn)綁定, this 指向全局對象
如果使用嚴(yán)格模式(strict mode),那么全局對象將無法使用默認(rèn)綁定,因此 this 會綁定到 undefined
觀察下面這段代碼
function aba () { console.log(this) } function bab () { "use strict" console.log(this) } var obj = { aba: aba, bab: bab } aba() //Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} bab() //undefined obj.aba() //{aba: ?, bab: ?} obj.bab() //{aba: ?, bab: ?}2. 隱式綁定
在一個(gè)對象內(nèi)部包含一個(gè)指向函數(shù)的屬性,并通過這個(gè)屬性間接引用函數(shù),從而把 this 間接(隱式)綁定到這個(gè)對象上。
當(dāng)函數(shù)引用有上下文對象時(shí),隱式綁定規(guī)則會把函數(shù)調(diào)用中的 this 綁定到這個(gè)上下文對象。
所以上個(gè)示例代碼中, 調(diào)用 obj.aba()時(shí) this 被綁定到 obj,因此 this.aba 和 obj.aba 是一樣的。
對象屬性引用鏈中只有
最頂層或者說最后一層會影響調(diào)用位置。
function foo() { console.log( this.a ); } var obj2 = { a: 42, foo: foo }; var obj1 = { a: 2, obj2: obj2 }; obj1.obj2.foo(); // 42
一個(gè)最常見的 this 綁定問題就是被隱式綁定的函數(shù)會丟失綁定對象,也就是說它會應(yīng)用默認(rèn)綁定,從而把 this 綁定到全局對象或者 undefined 上,取決于是否是嚴(yán)格模式。
function fun1 () { console.log(this) } var obj = { fun1: fun1, fun2: function () { console.log(this) } } var getfun1 = obj.fun1 var getfun2 = obj.fun2 function doCallBack (cb) { //參數(shù)傳遞其實(shí)就是一種隱式賦值,因此我們傳入函數(shù)時(shí)也會被隱式賦值 cb() } function testSetTimeout (fun) { setTimeout(fun, 0) } fun1() // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} obj.fun1() // {fun1: ?, fun2: ?} obj.fun2() // {fun1: ?, fun2: ?} getfun1() // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} getfun2() // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} doCallBack(obj.fun1) // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} doCallBack(obj.fun2) // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} testSetTimeout(obj.fun1) // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…} testSetTimeout(obj.fun2) // Window {frames: Window, postMessage: ?, blur: ?, focus: ?, close: ?,?…}3. 顯式綁定
使用 call 、 apply 、 bind 或者箭頭函數(shù)顯示綁定函數(shù)調(diào)用的 this
如果把 null 或者 undefined 作為 this 的綁定對象傳入 call、apply 或者 bind,這些值在調(diào)用時(shí)會被忽略,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則
var obj = { c: 33, fun: function (a,b) { console.log( "a:" + a + ", b:" + b + ", c:" + this.c ) } } // 把數(shù)組“展開”成參數(shù) obj.fun.apply( null, [2, 3] ); a:2, b:3, c:undefined // 使用 bind(..) 進(jìn)行柯里化 var bar = obj.fun.bind( null, 2 ); bar( 3 ); // a:2, b:3, c:undefined
上面代碼中 apply 、 bind 這兩種方法都需要傳入一個(gè)參數(shù)當(dāng)作 this 的綁定對象。如果函數(shù)并不關(guān)心 this 的話,仍然需要傳入一個(gè)占位值,這時(shí) null 可能是一個(gè)不錯(cuò)的選擇。
但是如果某個(gè)函數(shù)確實(shí)使用了 this,那默認(rèn)綁定規(guī)則會把 this 綁定到全局對象(在瀏覽器中這個(gè)對象是 window),這將導(dǎo)致不可預(yù)計(jì)的后果(比如修改全局對象)。
在 JavaScript 中,構(gòu)造函數(shù)只是一些被 new 操作符調(diào)用的普通函數(shù)而已。
實(shí)際上并不存在所謂的“構(gòu)造函數(shù)”,只有對于函數(shù)的“構(gòu)造調(diào)用”。使用 new 來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時(shí),會自動(dòng)執(zhí)行下面的操作。
1 創(chuàng)建(或者說構(gòu)造)一個(gè)全新的對象。
2 這個(gè)新對象會被執(zhí)行 [[ 原型 ]] 連接。
3 這個(gè)新對象會綁定到函數(shù)調(diào)用的 this。
4 如果函數(shù)沒有返回其他對象,那么 new 表達(dá)式中的函數(shù)調(diào)用會自動(dòng)返回這個(gè)新對象。
注意: 對 bind 返回的函數(shù)進(jìn)行構(gòu)造調(diào)用時(shí),實(shí)際調(diào)用的是原函數(shù),調(diào)用 bind 時(shí)傳入的第一個(gè)參數(shù)將被忽略,剩余參數(shù)作為構(gòu)造調(diào)用的參數(shù)傳入原函數(shù)
function test (a, b) { this.a = a this.b = b this.say = function () { console.log(`a: ${this.a}, b: ${this.b}, c: ${this.c}`) } } var bindObj = { c: 12 } var bindReturn = test.bind(bindObj, 1, 2) var newBindReturn = new bindReturn() newBindReturn.say() // a: 1, b: 2, c: undefined console.log(bindObj) // {c: 12} bindReturn() console.log(bindObj) // {c: 12, a: 1, b: 2, say: ?}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/90087.html
摘要:注此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀你不知道的后的理解。作用域及閉包基礎(chǔ),代碼運(yùn)行的幕后工作者引擎及編譯器。 注:此讀書筆記只記錄本人原先不太理解的內(nèi)容經(jīng)過閱讀《你不知道的JS》后的理解。 作用域及閉包基礎(chǔ),JS代碼運(yùn)行的幕后工作者:引擎及編譯器。引擎負(fù)責(zé)JS程序的編譯及執(zhí)行,編譯器負(fù)責(zé)詞法分析和代碼生成。那么作用域就像一個(gè)容器,引擎及編譯器都從這里提取東西。 ...
摘要:有種內(nèi)置類型,分別是除對象之外,其他統(tǒng)稱為基本類型。另一個(gè)需要注意的是數(shù)組確切地說,數(shù)組也是的一個(gè)子類型我們可以通過下面的方法檢查變量是不是數(shù)組處理未聲明的變量時(shí),會返回這是因?yàn)橛幸粋€(gè)特殊的安全防范機(jī)制。 js有7種內(nèi)置類型,分別是undefined null boolean string number symbol object除對象之 Object 外,其他統(tǒng)稱為基本類型。符號 ...
摘要:本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點(diǎn),不會全記,供大家和自己翻閱不錯(cuò),下冊的知識點(diǎn)就這么少,非常不推介看下冊上中下三本的讀書筆記你不知道的上讀書筆記你不知道的中讀書筆記你不知道的下讀書筆記第三 本書屬于基礎(chǔ)類書籍,會有比較多的基礎(chǔ)知識,所以這里僅記錄平常不怎么容易注意到的知識點(diǎn),不會全記,供大家和自己翻閱; 不錯(cuò),下冊的知識點(diǎn)就這么少,非...
摘要:閉包在循環(huán)中的應(yīng)用延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時(shí)才執(zhí)行事實(shí)上,當(dāng)定時(shí)器運(yùn)行時(shí)即使沒給迭代中執(zhí)行的是多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個(gè)出來。 閉包在循環(huán)中的應(yīng)用 延遲函數(shù)的回調(diào)會在循環(huán)結(jié)束時(shí)才執(zhí)行;事實(shí)上,當(dāng)定時(shí)器運(yùn)行時(shí)即使沒給迭代中執(zhí)行的是 setTime(..., 0),多有的回調(diào)函數(shù)依然是在循環(huán)結(jié)束后才會被執(zhí)行,因此會每次輸出一個(gè)6出來。 for(var...
摘要:的分句會創(chuàng)建一個(gè)塊作用域,其聲明的變量僅在中有效。而閉包的神奇作用是阻止此事發(fā)生。依然持有對該作用域的引用,而這個(gè)引用就叫做閉包。當(dāng)然,無論使用何種方式對函數(shù)類型的值進(jìn)行傳遞,當(dāng)函數(shù)在別處被調(diào)用時(shí)都可以觀察到閉包。 date: 16.12.8 Thursday 第一章 作用域是什么 LHS:賦值操作的目標(biāo)是誰? 比如: a = 2; RHS:誰是賦值操作的源頭? 比如: conso...
閱讀 1342·2021-11-25 09:43
閱讀 1902·2021-11-12 10:36
閱讀 6007·2021-09-22 15:05
閱讀 3485·2019-08-30 15:55
閱讀 2014·2019-08-26 14:06
閱讀 3645·2019-08-26 12:17
閱讀 504·2019-08-23 17:55
閱讀 2456·2019-08-23 16:23