摘要:作為方法進(jìn)行調(diào)用,該上下文是方法的擁有者作為全局函數(shù)調(diào)用,其上下文永遠(yuǎn)是也就是說(shuō),該函數(shù)是的一個(gè)方法作為構(gòu)造器進(jìn)行調(diào)用時(shí),其上下文對(duì)象則是新創(chuàng)建的對(duì)象實(shí)例。
精確把握 JavaScript 中的 this
this 是 JavaScript 中的一個(gè)關(guān)鍵字,當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),除了傳入函數(shù)的顯式參數(shù)以外,名為 this 的隱式參數(shù)也被傳入了函數(shù)。this 參數(shù)指向了一個(gè)自動(dòng)生成的內(nèi)部對(duì)象,這個(gè)內(nèi)部對(duì)象被稱(chēng)為函數(shù)上下文。與其他面向?qū)ο蟮恼Z(yǔ)言不同的是, JavaScript 中的 this 依賴(lài)于函數(shù)的調(diào)用方式。所以,想要明白 this 的指向問(wèn)題,還必須先研究函數(shù)在 JavaScript 中是如何被調(diào)用的。
調(diào)用方式 1、作為函數(shù)進(jìn)行調(diào)用這說(shuō)法有點(diǎn)奇怪,函數(shù)當(dāng)然是被作為函數(shù)進(jìn)行調(diào)用的,但我們說(shuō)一個(gè)函數(shù)“作為函數(shù)”被調(diào)用,只是為了區(qū)別于其他的調(diào)用方式。先看一個(gè)簡(jiǎn)單的例子:
function func1() { console.log(this === window); // true } func1(); var func2 = function () { console.log(this === window); // true } func2(); function func3() { "use strict"; console.log(this); // undefined } func3();
上面例子中的第一第二個(gè) this 在非嚴(yán)格模式下指向全局上下文,即 window 對(duì)象,第三個(gè)在嚴(yán)格模式下則為 undefined。
所以,當(dāng)函數(shù)被作為函數(shù)進(jìn)行調(diào)用時(shí),在非嚴(yán)格模式下,函數(shù)的上下文是 window 對(duì)象,而在嚴(yán)格模式下,函數(shù)上下文為 undefined。
調(diào)用方式 2、作為方法進(jìn)行調(diào)用當(dāng)一個(gè)函數(shù)被賦值給一個(gè)對(duì)象的一個(gè)屬性,并使用引用該函數(shù)的這個(gè)屬性進(jìn)行調(diào)用函數(shù)時(shí),那么函數(shù)就是作為該對(duì)象的一個(gè)方法進(jìn)行調(diào)用的。看下面的例子:
var obj = { func: function() { console.log(this === obj); // true } }; obj.func();
上面的例子中,函數(shù) func 的調(diào)用對(duì)象為 obj,所以函數(shù)上下文便是 obj。由此可見(jiàn),將函數(shù)作為對(duì)象的一個(gè)方法進(jìn)行調(diào)用時(shí),該對(duì)象就是函數(shù)上下文,并且在函數(shù)內(nèi)部可以用 this 來(lái)訪(fǎng)問(wèn)這個(gè)對(duì)象。
此時(shí),我們?cè)倏匆幌碌谝环N調(diào)用方式,即“作為函數(shù)”調(diào)用。“作為函數(shù)”進(jìn)行調(diào)用的函數(shù)是定義在 window 上的,調(diào)用時(shí)也不需要 window 的引用,其實(shí)方式 1 中例子中的 func1() 就是 window.func1(),所以例子中的函數(shù)上下文便是 this。
調(diào)用方式 3、作為構(gòu)造器進(jìn)行調(diào)用將函數(shù)作為構(gòu)造器時(shí),函數(shù)的聲明與其他調(diào)用方式的函數(shù)聲明一致。將函數(shù)作為構(gòu)造器調(diào)用的例子如下:
function Student() { this.getContext = function() { return this; } } var stu = new Student(); console.log(stu.getContext() === stu); // true
將函數(shù)作為構(gòu)造器調(diào)用時(shí),便會(huì)通過(guò)這個(gè)函數(shù)生成一個(gè)新對(duì)象,這時(shí),this 指向這個(gè)新創(chuàng)建的對(duì)象。
從上面幾種調(diào)用方式來(lái)看,函數(shù)調(diào)用方式之間的主要差異是:作為 this 參數(shù)傳遞給執(zhí)行函數(shù)的上下文對(duì)象之間的區(qū)別。作為方法進(jìn)行調(diào)用,該上下文是方法的擁有者;作為全局函數(shù)調(diào)用,其上下文永遠(yuǎn)是 window (也就是說(shuō),該函數(shù)是 window 的一個(gè)方法);作為構(gòu)造器進(jìn)行調(diào)用時(shí),其上下文對(duì)象則是新創(chuàng)建的對(duì)象實(shí)例。
下面的一種調(diào)用方式可以顯式地指定上下文。
調(diào)用方式 4、使用 apply() 和 call() 方法進(jìn)行調(diào)用JavaScript 的每個(gè)函數(shù)都有 apply() 和 call() 函數(shù),可以利用任何一個(gè)函數(shù)都可以顯式指定任何一個(gè)對(duì)象作為其函數(shù)上下文。
通過(guò) apply() 方法來(lái)調(diào)用函數(shù),我們要給 apply() 傳入兩個(gè)參數(shù):一個(gè)作為函數(shù)上下文對(duì)象,另一個(gè)作為函數(shù)參數(shù)所組成的數(shù)組。call() 方法的使用方式類(lèi)似,唯一不同的是給函數(shù)傳入的參數(shù)是一個(gè)參數(shù)列表,而不是單個(gè)數(shù)組。
function func() { var result = 0; for(var i = 0; i < arguments.length; i++) { result += arguments[i]; } this.result = result; } var obj1 = {}; var obj2 = {}; func.apply(obj1, [1, 2, 3]); func.call(obj2, 4, 5, 6); console.log(obj1.result === 6); // true console.log(obj2.result === 15); // true
在上面的代碼中,func.apply(obj1, [1, 2, 3]); 將函數(shù)的上下文定義為 obj1,并且傳入 1、2、3 三個(gè)參數(shù),func.call(obj2, 4, 5, 6); 將函數(shù)的上下文定義為 obj2,并且傳入 4、5、6 三個(gè)參數(shù)。
那 apply 和 call 基本相同,那么我們?cè)撚媚囊粋€(gè)呢?其實(shí) apply 和 call 的區(qū)別僅僅在于調(diào)用時(shí)傳入的參數(shù)不同,其他完全一樣。所以,在選擇時(shí),主要看傳入的參數(shù)。如果已知參數(shù)已經(jīng)在數(shù)組里了則用 apply 即可,或者參數(shù)是動(dòng)態(tài)生成的,可以把參數(shù) push 進(jìn)一個(gè)數(shù)組,然后再用 apply 調(diào)用。當(dāng)參數(shù)數(shù)量已知,或者在參數(shù)里有很多無(wú)關(guān)的值則用 call 方法調(diào)用。
其他補(bǔ)充 利用 bind() 改變函數(shù)上下文先看下面例子:
var obj1 = { a: 1 }; var obj2 = { a: 2, func: function() { console.log(this.a); }.bind(obj1) }; obj2.func(); // 1
ECMAScript 5 引入了 Function.prototype.bind,其會(huì)創(chuàng)建一個(gè)綁定函數(shù),當(dāng)調(diào)用這個(gè)綁定函數(shù)時(shí),函數(shù)上下文將會(huì)是 bind() 方法的第一個(gè)參數(shù)。上面的例子中,將 obj1 設(shè)置為函數(shù)上下文,所以利用 func 來(lái)調(diào)用函數(shù)時(shí),函數(shù)的上下文為 obj1,而不是它的調(diào)用者 obj2。
利用 Array 的 5 個(gè)方法改變函數(shù)上下文5 個(gè)方法分別是:
Array.prototype.every(callbackfn [, thisArg ])
Array.prototype.some(callbackfn [, thisArg ])
Array.prototype.forEach(callbackfn [, thisArg ])
Array.prototype.map(callbackfn [, thisArg ])
Array.prototype.filter(callbackfn [, thisArg ])
當(dāng)調(diào)用以上 5 個(gè)方法時(shí),傳入的參數(shù)除了回調(diào)函數(shù)以外,還可以傳入另外一個(gè)可選地參數(shù),即函數(shù)上下文,代表回調(diào)函數(shù)中的函數(shù)上下文。如果省略該參數(shù),則 callback 被調(diào)用時(shí)的 this 值,在非嚴(yán)格模式下為全局對(duì)象,在嚴(yán)格模式下傳入 undefined。看下面的例子:
var arr = ["segmentfault"]; var obj = {}; arr.forEach(function(ele, ind) { console.log(this === window); // true }); arr.forEach(function(ele, ind) { console.log(this === obj); // true }, obj);測(cè)試
在網(wǎng)上找了幾個(gè)代碼小例子,來(lái)測(cè)試對(duì)上面內(nèi)容的理解,答案在最下面。
1、if (true) { // this }2、
var obj = { someData: "a string" }; function myFun() { // this } obj.staticFunction = myFun; obj.staticFunction();3、
var obj = { myMethod : function () { // this } }; var myFun = obj.myMethod; myFun();4、
function myFun() { // this } var obj = { someData: "a string" }; myFun.call(obj);答案
1、window
2、obj
3、window
4、obj
注:以上代碼均在瀏覽器環(huán)境中測(cè)試。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/78823.html
摘要:效果圖如下代碼日第一個(gè)參數(shù)代表是否是今天的日歷,如果第一個(gè)參數(shù)為,還需要傳遞倆個(gè)參數(shù),年和月。如何制作控制月份的控件方法如下得到頁(yè)面上的對(duì)象控件。 效果圖如下:showImg(https://segmentfault.com/img/bV0rKL?w=379&h=221); html代碼 - 2017/12 + 1234...
摘要:效果圖如下代碼日第一個(gè)參數(shù)代表是否是今天的日歷,如果第一個(gè)參數(shù)為,還需要傳遞倆個(gè)參數(shù),年和月。如何制作控制月份的控件方法如下得到頁(yè)面上的對(duì)象控件。 效果圖如下:showImg(https://segmentfault.com/img/bV0rKL?w=379&h=221); html代碼 - 2017/12 + 1234...
摘要:效果圖如下代碼日第一個(gè)參數(shù)代表是否是今天的日歷,如果第一個(gè)參數(shù)為,還需要傳遞倆個(gè)參數(shù),年和月。如何制作控制月份的控件方法如下得到頁(yè)面上的對(duì)象控件。 效果圖如下:showImg(https://segmentfault.com/img/bV0rKL?w=379&h=221); html代碼 - 2017/12 + 1234...
摘要:繼承關(guān)鍵字傳給父類(lèi)執(zhí)行實(shí)際應(yīng)用就是提取公共部分,復(fù)用代碼。關(guān)于封裝,完全開(kāi)發(fā)對(duì)子類(lèi)開(kāi)放對(duì)自己開(kāi)放,目前還不支持。 showImg(https://segmentfault.com/img/remote/1460000016136611?w=800&h=355); showImg(https://segmentfault.com/img/remote/1460000016136612);...
摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號(hào),更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。若有幫助,請(qǐng)把課多周刊推薦給你的朋友,你的支持是我們最大的動(dòng)力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時(shí)一運(yùn)維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號(hào):fed-talk,更多精彩內(nèi)容皆在微信公眾號(hào),歡迎關(guān)注。 若有幫助,請(qǐng)把 課多周刊 推薦給你的朋友,你的支持是我們最大的...
閱讀 2066·2021-09-22 15:54
閱讀 1830·2021-09-04 16:40
閱讀 854·2019-08-30 15:56
閱讀 2623·2019-08-30 15:44
閱讀 2150·2019-08-30 13:52
閱讀 1120·2019-08-29 16:35
閱讀 3340·2019-08-29 16:31
閱讀 2562·2019-08-29 13:48