摘要:關(guān)于的指向的問(wèn)題請(qǐng)參照我的學(xué)習(xí)筆記。那么在這里事實(shí)上都改變了函數(shù)方法被調(diào)用時(shí)的指向。那么回調(diào)函數(shù)在執(zhí)行的時(shí)候指向還是。大家看完之后應(yīng)該已經(jīng)懂了把還是不懂的話(huà)在評(píng)論區(qū)留言,我給大家解答。
先從一個(gè)小題目開(kāi)始吧:
要實(shí)現(xiàn)一個(gè)加法函數(shù),這個(gè)時(shí)候向函數(shù)當(dāng)中傳遞個(gè)數(shù)大于0的若干個(gè)整形數(shù)據(jù),求所有這些數(shù)據(jù)的和。
Function.prototype.call
Function.prototype.apply
Function.prototype.bind
其中call方法:
var personA = { name: "XL", sayName: function (hobby){ console.log(this.name + " likes " + hobby); } }; personA.sayName("basketball"); // "XL likes basketball" var personB = { name: "xl" } personA.sayName.call(personB, "basketball"); // "xl likes basketball" personA.sayName.apply(personB, ["basketball"]); // "xl likes basketball"
call和apply的區(qū)別就在于傳遞方式的不同,call在接收指定參數(shù)的形式是someMethod.call(obj, arg1, arg2);而apply在接收指定參數(shù)時(shí)的形式是someMethod.apply(obj, [arg1, arg2]).或者someMethod.apply(obj, arg1),但是這個(gè)arg1必須是一個(gè)類(lèi)數(shù)組對(duì)象
其實(shí)想要真正掌握call/apply包括bind方法,首先必須搞清楚當(dāng)一個(gè)函數(shù)/方法被調(diào)用的時(shí)候this的指向問(wèn)題。 關(guān)于this的指向的問(wèn)題請(qǐng)參照我的學(xué)習(xí)筆記。
那么在這里call,apply,bind事實(shí)上都改變了函數(shù)/方法被調(diào)用時(shí)this的指向。
還是拿上面的例子來(lái)說(shuō):
personA.sayName(‘basketball’); //調(diào)用sayName()這個(gè)方法的對(duì)象是personA,因此sayName()內(nèi)部的this指向就是personA對(duì)象
換一種寫(xiě)法
var sayName = personA.sayName("basketball"); //這里將sayName方法掛載到了window對(duì)象上,即window.sayName = person.sayName(); 這個(gè)時(shí)候調(diào)用sayName().此時(shí)this指向就是window對(duì)象
使用call/apply
personA.sayName.call(personB, "basketball"); //本來(lái)sayName方法的this指向是personA對(duì)象,但是調(diào)用call后,this對(duì)象指向了personB對(duì)象。
如果大家這種寫(xiě)法看不習(xí)慣,那就換種方式來(lái)看:
personA.sayName.call(personB, "basketball") ===> personB.sayName("basketball"); //從前面的一個(gè)形式變?yōu)楹竺嬉环N形式,此時(shí),sayName方法的this指向是personB對(duì)象了。
換一種方式書(shū)寫(xiě)后大家應(yīng)該看的很清晰明了了吧?以后碰到call/apply調(diào)用的時(shí)候,換一種形式去理解,這樣就很清晰了。
再比如大家經(jīng)??吹降囊环N對(duì)于函數(shù)的arguments類(lèi)數(shù)組對(duì)象的處理方式:
function fn() { var args = Array.prototype.slice.apply(arguments); //這里將arguments這個(gè)類(lèi)數(shù)組對(duì)象轉(zhuǎn)化為一個(gè)數(shù)組 } //咱們?cè)賮?lái)轉(zhuǎn)化下: Array.prototype.slice.apply(arguments); ===>>> arguments.slice(); //因?yàn)閍rguments是類(lèi)數(shù)組對(duì)象的原因,因此它可以直接調(diào)用slice方法;如果要截取數(shù)組的從第幾位到第幾位的數(shù) Array.prototype.slice.apply(arguments, [0, 2]); ===>>> arguments.slice(0, 2);
握草,感覺(jué)編不下去了- -
其實(shí)將call/apply,換一種形式去看,是不是就和普通的方法調(diào)用一樣一樣的。
bind方法呢,起的作用和call,apply一樣,都是改變函數(shù)/方法執(zhí)行時(shí),this的指向,確保這個(gè)函數(shù)/方法運(yùn)行時(shí)this指向保持一致。
比如大家經(jīng)常用到的setTimeout異步函數(shù):
var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }, 0); } } person.sayName(); //最后輸出: undefined
這是因?yàn)?b>setTimeout()這個(gè)異步函數(shù)調(diào)用的時(shí)候,內(nèi)部的回調(diào)函數(shù)this的指向是window.但是在window對(duì)象上并未掛載name屬性,因此最后輸出undefined.
添加一行代碼
var name = "XLLLL"; var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }, 0); } } person.sayName(); //輸出 ‘XLLLL’
為了避免在回調(diào)函數(shù)當(dāng)中,this指向發(fā)生變化,所以大家都會(huì)這樣處理:
var person = { name: "XL", sayName: function() { setTimeout(function() { console.log(this.name); }.bind(this), 0); //通過(guò)bind方法將this對(duì)象綁定為person。那么回調(diào)函數(shù)在執(zhí)行的時(shí)候,this指向還是person。 } }
可以用下面這段代碼來(lái)簡(jiǎn)單模擬下bind方法內(nèi)部的操作:
Function.prototype.bind = function(obj) { var method = this; return function() { method.apply(obj, arguments); } }
還記得剛才給大家講的將apply進(jìn)行變換的形式嗎?
Function.prototype.bind = function(obj) { var method = this; return function() { obj.method(arguments); } }
大家應(yīng)該看到了bind和apply/call的區(qū)別了吧? bind方法是返回一個(gè)新的函數(shù),但是這個(gè)函數(shù)比較特殊,這個(gè)函數(shù)的this對(duì)象已經(jīng)被bind方法傳入的第一個(gè)參數(shù)給綁定了.
比如我們可以使用bind方法來(lái)簡(jiǎn)寫(xiě)一個(gè)方法:
function fn() { var hasOwnKey = Function.call.bind(Object.hasOwnProperty); for(var key in obj) { if(hasOwnKey(obj, key)) { //xxxx } } }
唉,真的編不下去了。大家看完之后應(yīng)該已經(jīng)懂了把? - -
還是不懂的話(huà)在評(píng)論區(qū)留言,我給大家解答。
哦,一開(kāi)始那個(gè)題目的一種寫(xiě)法
//要實(shí)現(xiàn)一個(gè)加法函數(shù),這個(gè)時(shí)候向函數(shù)當(dāng)中傳遞個(gè)數(shù)大于0的若干個(gè)整形數(shù)據(jù),求所有這些數(shù)據(jù)的和。 function add() { return Array.prototype.reduce.call(arguments, function(n1, n2) { return n1 + n2; }); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/80464.html
摘要:最近剛剛看完了你不知道的上卷,對(duì)有了更進(jìn)一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對(duì)象原型。附錄詞法這一章并沒(méi)有說(shuō)明機(jī)制,只是介紹了中的箭頭函數(shù)引入的行為詞法。第章混合對(duì)象類(lèi)類(lèi)理論類(lèi)的機(jī)制類(lèi)的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對(duì) JavaScript 有了更進(jìn)一步的了解。 《你不知道的 JavaScript》上卷由兩部...
摘要:總結(jié)動(dòng)態(tài)代理的相關(guān)原理已經(jīng)講解完畢,接下來(lái)讓我們回答以下幾個(gè)思考題。 【干貨點(diǎn)】 此處是【好好面試】系列文的第12篇文章。文章目標(biāo)主要是通過(guò)原理剖析的方式解答Aop動(dòng)態(tài)代理的面試熱點(diǎn)問(wèn)題,通過(guò)一步步提出問(wèn)題和了解原理的方式,我們可以記得更深更牢,進(jìn)而解決被面試官卡住喉嚨的情況。問(wèn)題如下 SpringBoot默認(rèn)代理類(lèi)型是什么 為什么不用靜態(tài)代理 JDK動(dòng)態(tài)代理原理 CGLIB動(dòng)態(tài)代理...
摘要:系統(tǒng),扎實(shí)的語(yǔ)言基礎(chǔ)是一個(gè)優(yōu)秀的前端工程師必須具備的。第一個(gè)參數(shù)為調(diào)用函數(shù)時(shí)的指向,隨后的參數(shù)則作為函數(shù)的參數(shù)并調(diào)用,也就是。和的區(qū)別只有一個(gè),就是它只有兩個(gè)參數(shù),而且第二個(gè)參數(shù)為調(diào)用函數(shù)時(shí)的參數(shù)構(gòu)成的數(shù)組。 系統(tǒng),扎實(shí)的 javascript 語(yǔ)言基礎(chǔ)是一個(gè)優(yōu)秀的前端工程師必須具備的。在看了一些關(guān)于 call,apply,bind 的文章后,我還是打算寫(xiě)下這篇總結(jié),原因其實(shí)有好幾個(gè)。...
摘要:包中導(dǎo)出的默認(rèn)是運(yùn)行時(shí)構(gòu)建。當(dāng)然,我們期待的是只修改代碼,不用重新運(yùn)行命令,甚至不需要刷新瀏覽器即看到代碼的改動(dòng)效果,這時(shí)候需要新的插件來(lái)配置實(shí)現(xiàn)的熱重載。 首先已經(jīng)全局安裝了node/vue/webpack; 新建文件夾demo4并初始化 cd demo4 npm init -y 這是頁(yè)面會(huì)生成一個(gè)package.json文件。 安裝webpack及相關(guān)插件 npm install ...
摘要:綁定書(shū)中提到在中,實(shí)際上并不存在所謂的構(gòu)造函數(shù),只有對(duì)于函數(shù)的構(gòu)造調(diào)用。規(guī)則使用構(gòu)造調(diào)用的時(shí)候,會(huì)自動(dòng)綁定在期間創(chuàng)建的對(duì)象上。指向新創(chuàng)建的對(duì)象綁定比隱式綁定優(yōu)先級(jí)高。 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1fstcwvzkjzj30sg0g0qqn.jpg); 前言 最近正在看《你不知道的JavaScript》,里面關(guān)于this綁...
閱讀 3519·2019-08-30 15:44
閱讀 860·2019-08-30 13:46
閱讀 2238·2019-08-30 11:05
閱讀 3407·2019-08-29 18:32
閱讀 2269·2019-08-29 13:56
閱讀 1372·2019-08-29 12:57
閱讀 816·2019-08-28 18:21
閱讀 1860·2019-08-26 12:16