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