摘要:目錄一理解指針意義二用解決指針指向問題三的使用場景與少用之處一理解指針意義讓我們先理解好指針的定義引用的是函數(shù)執(zhí)行的環(huán)境對(duì)象永遠(yuǎn)指向的是最后調(diào)用它的對(duì)象,也就是看它執(zhí)行的時(shí)候是誰調(diào)用的通俗地講,就是誰調(diào)用,就指向誰我們分類舉例舉例前先看下本
目錄
一.理解this指針意義
二.用call(),apply(),bind()解決指針指向問題
三.bind()的使用場景與少用之處
讓我們先理解好this指針的定義:
this引用的是函數(shù)執(zhí)行的環(huán)境對(duì)象
this永遠(yuǎn)指向的是最后調(diào)用它的對(duì)象,也就是看它執(zhí)行的時(shí)候是誰調(diào)用的
通俗地講,就是誰調(diào)用this,this就指向誰,我們分類舉例
舉例前先看下本文會(huì)一直用到的變量及定義的函數(shù)
var theName = "Joe"; //全局變量 function showName() { var theName = "Li"; alert(this.theName); }1.全局直接調(diào)用方法
showName(); //彈出“Joe”
因?yàn)槭?b>window對(duì)象調(diào)用showName(),所以this指向window啦,故彈出"Joe"
2.對(duì)象中調(diào)用全局下的方法var student1 = { theGrade : 100, theName : "Han", showName : showName, showGrade : function () { alert(this.theGrade); } }; student1.showName();//彈出“Han” student1.showGrade();//彈出“100”
因?yàn)槭窃?b>student1對(duì)象調(diào)用函數(shù),故彈出的是對(duì)應(yīng)student1對(duì)象中的"Han"和“100”啦
3.對(duì)象中調(diào)用其他對(duì)象的方法var student2 = { theGrade: 60, showGrade: student1.showGrade }; student2.showGrade(); //彈出"60"
即使student2對(duì)象調(diào)用了student1對(duì)象下的方法showGrade(),因?yàn)槭?b>student2對(duì)象調(diào)用,故彈出的仍是student2的"60"
4.對(duì)象的方法賦給全局變量執(zhí)行var outFunction = student1.showGrade; outFunction();//彈出“undefined”
將sutdent1對(duì)象的函數(shù)賦值給oufFuncction,而outFunction是在window對(duì)象下調(diào)用的,故彈出“undefined”
5.構(gòu)造函數(shù)下的this指針function setStudent() { this.theName = "Ming"; } var student3 = new setStudent(); alert(student3.theName);//彈出“Ming”,new改變this指向
構(gòu)造函數(shù)下,new改變了指針指向,指向了student3
6.事件監(jiān)聽中創(chuàng)建閉包的this指針關(guān)鍵:閉包保存創(chuàng)建時(shí)的環(huán)境?。?!
舉個(gè)例子
為了更好理解閉包與指針的關(guān)系,我們先定義一個(gè)全局變量,一個(gè)函數(shù),和一個(gè)對(duì)象
var example = "window";//全局變量 function showExample() { console.log(this.example); } var exampleObject = { example : "Object", showExample_in_Object : function (arg1, arg2) { console.log(this.example); console.log(arg1,arg2) } };
接著,我們?cè)O(shè)置一個(gè)事件監(jiān)聽來說明問題:
//事件監(jiān)聽 var btn = document.getElementById("btn"); btn.onclick = function (ev) { console.log(this); //this指向按鈕,執(zhí)行匿名函數(shù)的是btn this.example = "ele"; console.log(this.example);//彈出"ele" showExample(); //閉包保存函數(shù)創(chuàng)建時(shí)的環(huán)境,故this指向window對(duì)象 exampleObject.showExample_in_Object();//this指向exampleObject };
結(jié)果:
接下來分段說明各個(gè)指針
其中
????this.example = "ele"; ????console.log(this.example);
其中的this指向btn,所以顯示的是‘ele’
而
????showExample(); ?? ?? ????exampleObject.showExample_in_Object();?? ?
在匿名函數(shù)中為閉包,閉包保存函數(shù)創(chuàng)建時(shí)的環(huán)境,故this分別指向window和exampleObject
補(bǔ)充對(duì)閉包中this的理解:https://segmentfault.com/q/10...
以上是部分this指針的理解
如果我在事件監(jiān)聽中想要減少代碼重復(fù),或者是調(diào)用其他對(duì)象的屬性呢?
如果我想用btn.addEventListener()時(shí)指向的某個(gè)特定對(duì)象呢?
這就可以引出下面call(),apply()與bind()的應(yīng)用了
7.函數(shù)中自執(zhí)行函數(shù)指向function User(id){ this.id = id; } User.prototype.test = function(){ console.log(this);//指向b對(duì)象 (function(){ console.log(this) //指向window })() } var a = new User("a") a.test();
因?yàn)樽詧?zhí)行函數(shù)是由window執(zhí)行的
如果此時(shí)使用箭頭函數(shù)
function User2(id){ this.id = id; } User.prototype.test = function(){ console.log(this); //指向b對(duì)象 (() =>{ console.log(this) //指向b對(duì)象 })() } var b = new User2("b"); b.test();
因?yàn)榧^函數(shù)不會(huì)綁定this,所以指向上一層的b對(duì)象
二.用call(),apply(),bind()解決指針指向問題 1.call()與apply()call()與apply()的作用都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)設(shè)置this對(duì)象的值
簡單地說,就是可以改變函數(shù)的執(zhí)行環(huán)境
call()與allpy()效果相同,僅是傳參形式不同,如下所示
call(): fun.call(thisArg,?arg1,?arg2, ...) thisArg : fun函數(shù)運(yùn)行時(shí)指定的this值 arg1,arg2,.. (可選):指定的各個(gè)參數(shù)
apply(): func.apply(thisArg, [argsArray]) thisArg : fun函數(shù)運(yùn)行時(shí)指定的this值 [argsArray](可選) : 傳參數(shù)組或者傳參類數(shù)組
下面直接看例子吧
我們以上面的例子進(jìn)行修改,為了對(duì)比傳參的形式,我們對(duì)showExample函數(shù)添加兩個(gè)參數(shù)
function showExample(arg1,arg2) { console.log(this.example); console.log(arg1,arg2); }
接下來便是btn的點(diǎn)擊事件函數(shù)修改,我們令showExample函數(shù)指向exampleObject
//call與apply的應(yīng)用 btn.onclick = function (ev) { showExample.call(exampleObject,111,222); //彈出"Object" ,111與222是傳參示例 showExample.apply(exampleObject,[111,222]); //彈出"Object" ,[111,222]是傳參示例 }; 彈出"Object" ,111與222是傳參示例 showExample.apply(exampleObject,[111,222]); //彈出"Object" ,[111,222]是傳參示例 };
如上,通過call()與apply()的應(yīng)用,可以改變函數(shù)的指向而多次運(yùn)用
如果我想便于調(diào)試想使用ele.addEventListener()嘞?
這就要用上bind()方法了
2.bind()的運(yùn)用fun.bind(thisArg[, arg1[, arg2[, ...]]])
MDN?: bind()方法創(chuàng)建一個(gè)新的函數(shù), 當(dāng)被調(diào)用時(shí),將其this關(guān)鍵字設(shè)置為提供的值, ,在調(diào)用新函數(shù)時(shí),在任何提供之前提供一個(gè)給定的參數(shù)序列。
我們?cè)倥e個(gè)簡單的例子,將exampleObject簡單修改下
var exampleObject = { example : "Object", showExample_in_Object : function (arg1, arg2) { console.log(this); console.log("example:"+ this.example); console.log("arg1:" + arg1); console.log("arg2:" + arg2); } };
并把showExample_in_Object()函數(shù)添加給btn
注意這里的是函數(shù),不是閉包!
btn.addEventListener("click",exampleObject.showExample_in_Object);
控制臺(tái)顯示如下
?? ??? ??? ?
可以看出this指向的是btn,而無法滿足我們使用exampleObject中屬性的需要,同時(shí)也無法進(jìn)行傳參(用call()與apply()就直接執(zhí)行函數(shù)了!)
(這里的沒有對(duì)第一個(gè)參數(shù)arg1進(jìn)行傳參,故默認(rèn)顯示MouseEvent對(duì)象)
這時(shí)我們可以用bind()方法創(chuàng)建一個(gè)新的函數(shù),并讓其指針指向exampleObject,并傳兩個(gè)新的參數(shù)進(jìn)去
btn.addEventListener("click",exampleObject.showExample_in_Object.bind(exampleObject,111,222));
當(dāng)當(dāng)~指針指向了exampleObject,傳參也成功了~
另外,這里也有個(gè)可以不使用bind()的方法,就是也用閉包啦
btn.addEventListener("click",function () { exampleObject.showExample_in_Object(111,222); });
結(jié)果一樣,但這種方法不利于代碼的維護(hù),同時(shí)也無法指向特定的對(duì)象? ??
三.bind()的使用場景與少用之處使用場景:主要用于如上的事件監(jiān)聽,以及setTimeout()和setInterval()
少用之處:被綁定的函數(shù)與普通函數(shù)相比有更多的開銷,它們需要更多的內(nèi)存,同時(shí)也因?yàn)槎嘀睾瘮?shù)調(diào)用稍微慢一點(diǎn),所以最好只在必要時(shí)使用
以上,如有不對(duì)之處,請(qǐng)大家指教
參考資料:? ??徹底理解this指針:? ??https://www.cnblogs.com/pssp/...
? ? MDN:bind():?? ?https://developer.mozilla.org...
?? ?MDN:apply():https://developer.mozilla.org...
?? ?MDN:call():?? ?https://developer.mozilla.org...
?? ?《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》
?? ?《JavaScript語言精粹》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108554.html
摘要:它代表函數(shù)運(yùn)行時(shí),自動(dòng)生成的一個(gè)內(nèi)部對(duì)象,只能在函數(shù)內(nèi)部使用類似的還有??偨Y(jié)關(guān)鍵字就是,誰調(diào)用我,我就指向誰。注意由于已經(jīng)被定義為函數(shù)內(nèi)的一個(gè)變量。因此通過關(guān)鍵字定義或者將聲明為一個(gè)形式參數(shù),都將導(dǎo)致原生的不會(huì)被創(chuàng)建。 題目 封裝函數(shù) f,使 f 的 this 指向指定的對(duì)象 。 輸入例子 bindThis(function(a, b) { return this.test +...
摘要:詞法熟悉語法的開發(fā)者,箭頭函數(shù)在涉及綁定時(shí)的行為和普通函數(shù)的行為完全不一致。被忽略的作為的綁定對(duì)象傳入,使用的是默認(rèn)綁定規(guī)則。使用內(nèi)置遍歷數(shù)組返回迭代器函數(shù)普通對(duì)象不含有,無法使用,可以進(jìn)行改造,個(gè)人博客地址 this詞法 熟悉ES6語法的開發(fā)者,箭頭函數(shù)在涉及this綁定時(shí)的行為和普通函數(shù)的行為完全不一致。跟普通this綁定規(guī)則不一樣,它使用了當(dāng)前的詞法作用域覆蓋了this本來的值。...
摘要:它們有明確的和成員函數(shù)的定義,只有的實(shí)例才能調(diào)用這個(gè)的成員函數(shù)。用和調(diào)用函數(shù)里用和來指定函數(shù)調(diào)用的,即指針的指向。同樣,對(duì)于一個(gè)后的函數(shù)使用或者,也無法改變它的執(zhí)行,原理和上面是一樣的。 函數(shù)里的this指針 要理解call,apply和bind,那得先知道JavaScript里的this指針。JavaScript里任何函數(shù)的執(zhí)行都有一個(gè)上下文(context),也就是JavaScri...
摘要:首先,我們判斷是否存在方法,然后,若不存在,向?qū)ο蟮脑椭刑砑幼远x的方法。指向調(diào)用它的對(duì)象??傊齻€(gè)的使用區(qū)別都是用來改變函數(shù)的對(duì)象的指向的第一個(gè)參數(shù)都是要指向的對(duì)象都可以利用后續(xù)參數(shù)傳參是返回對(duì)應(yīng)函數(shù),便于稍后調(diào)用,是立即調(diào)用 apply和call都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上下文而存在的(就是為了改變函數(shù)內(nèi)部this的指向),F(xiàn)unction對(duì)象的方法,每個(gè)函數(shù)都能調(diào)用; 使用a...
摘要:使用構(gòu)造函數(shù)創(chuàng)建對(duì)象后,新對(duì)象與構(gòu)造函數(shù)沒有關(guān)系了,新對(duì)象的屬性指向的是構(gòu)造函數(shù)的原型對(duì)象。構(gòu)造繼承使用父類的構(gòu)造函數(shù)來增強(qiáng)子類的實(shí)例,等于是在子類的構(gòu)造函數(shù)內(nèi)部執(zhí)行。 一.js原始類型: 在js中,存在著6種原始值: * boolean * number * string * undefined * null * symbol 注意: 雖然typeof null輸出的是o...
閱讀 973·2023-04-26 02:49
閱讀 1185·2021-11-25 09:43
閱讀 2554·2021-11-18 10:02
閱讀 2930·2021-10-18 13:32
閱讀 1291·2019-08-30 13:54
閱讀 2088·2019-08-30 12:58
閱讀 3020·2019-08-29 14:06
閱讀 2162·2019-08-28 18:10