摘要:和區別其實他們的作用是一樣的,只是傳遞的參數不一樣而已。接受個參數,第一個參數指定了函數體內對象的指向,第二個參數為數組或者一個類數組。看個栗子一個有意思的事在中,多次是無效的。而則會立即執行函數。
背景
前兩天在做小程序的需求的時候用到bind的時候才想起自己對這三的東西的了解比較淺薄,這個時候用的時候就有點怕。時候還是要好好學習下,理解下怎么玩。
正文先說call 和 apply吧:
ECMAScript3給Function的原型定義了兩個方法,他們是Function.prototype.call 和 Function.prototype.apply. 在實際開發中,特別是在一些函數式風格的代碼編寫中,call和apply方法尤為有用。
1、call和apply區別
其實他們的作用是一樣的,只是傳遞的參數不一樣而已。
apply: 接受2個參數,第一個參數指定了函數體內this對象的指向,第二個參數為數組或者一個類數組。apply傳入的是一個參數數組,也就是將多個參數組合成為一個數組傳入,而call則作為call的參數傳入(從第二個參數開始)。
舉個栗子:
let obj1 = { name: "copyes", getName: function(){ return this.name; } } let obj2 = { name: "Fanchao" } console.log(obj1.getName()); // "copyes" console.log(obj1.getName.call(obj2)); // "Fanchao" console.log(obj1.getName.apply(obj2)); // "Fanchao"
function showArgs(a, b, c){ console.log(a,b,c); } showArgs.call(this, 3,4,5); showArgs.apply(this, [5,6,7]);
2、常見的call 和 apply 用法
數組之間追加
let arr1 = [12, "foo", {name: "fanchao"}, -1024]; let arr2 = ["copyes", "22", 1024]; Array.prototype.push.apply(arr1, arr2); console.log(arr1); // [ 12, "foo", { name: "fanchao" }, -1024, "copyes", "22", 1024 ]
獲取數組中的最大值和最小值
let numbers = [5,665,32,773,77,3,996]; let maxNum = Math.max.apply(Math, numbers); let maxNum2 = Math.min.call(Math, 5,665,32,773,77,3,996); console.log(maxNum); console.log(maxNum2);
驗證是否是數組(前提是toString()方法沒有被重寫過)
function isArray(obj){ return Object.prototype.toString.call(obj) === "[object Array]"; } console.log(isArray(1)); console.log(isArray([1,2]));
類(偽)數組使用數組方法
var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
3、通過一個面試題去深入理解下apply 和 call
定義一個 log 方法,讓它可以代理 console.log 方法:
// 常規做法 function log(msg){ console.log(msg); } log(12); log(1,2)
上面能夠基本解決打印輸出問題,但是下面多參數的時候就gg了。換個更好的方式吧。
function log(){ console.log.apply(console, arguments); } log(12); log(1,2)
接下來是要在每一條打印信息前面都要加上一個特定字符串"fanchao`s"又怎么說呢?
function log(){ let args = Array.prototype.slice.call(arguments); args.unshift("(fanchao`s)"); console.log.apply(console, args); } log(12); log(1,2)
4、說完了call和apply,接下來說說bind
bind() 方法與 apply 和 call 很相似,也是可以改變函數體內 this 的指向。
MDN的解釋是:bind()方法會創建一個新函數,稱為綁定函數,當調用這個綁定函數時,綁定函數會以創建它時傳入 bind()方法的第一個參數作為 this,傳入 bind() 方法的第二個以及以后的參數加上綁定函數運行時本身的參數按照順序作為原函數的參數來調用原函數。
看個栗子:
var func = function(){ console.log(this.x); console.log(arguments); } func(); // undefined, {} var obj = { x: 2 } var bar = func.bind(obj,1); bar(); // 2 , {"0":1}
一個有意思的事:
var bar = function() { console.log(this.x); } var foo = { x: 3 } var sed = { x: 4 } var func = bar.bind(foo).bind(sed); func(); //3 var fiv = { x: 5 } var func = bar.bind(foo).bind(sed).bind(fiv); func(); //3
在Javascript中,多次 bind() 是無效的。更深層次的原因, bind() 的實現,相當于使用函數在內部包了一個 call / apply ,第二次 bind() 相當于再包住第一次 bind() ,故第二次以后的 bind 是無法生效的。
5、這三個方法的異同點是什么呢?
還是先看個栗子:
var obj = { x: 81, }; var foo = { getX: function() { return this.x; } } console.log(foo.getX.bind(obj)()); //81 console.log(foo.getX.call(obj)); //81 console.log(foo.getX.apply(obj)); //81
看到bind后面對了一對括號。區別是,當你希望改變上下文環境之后并非立即執行,而是回調執行的時候,使用 bind() 方法。而 apply/call 則會立即執行函數。
總結apply 、 call 、bind 三者都是用來改變函數的this對象的指向的;
apply 、 call 、bind 三者第一個參數都是this要指向的對象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后續參數傳參;
bind是返回對應函數,便于稍后調用;apply、call則是立即調用 。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83332.html
在上一篇文章(《javascript高級程序設計》筆記:Function類型)中稍微提及了一下函數對象的屬性—this,在這篇文章中有深入的說明: 函數的三種簡單調用模式 1 函數模式 定義的函數,如果單獨調用,不將其與任何對象關聯,那么就是函數調用模式 function fn(num1, num2) { console.log(this); } // 直接在全局調用 fn();// w...
摘要:但是在調用函數值執行之后并沒有達到我們想要的效果。解析在這里我們為每一個的事件綁定了一個匿名函數,這個匿名函數就形成了一個閉包。這樣我們就為每個的事件的匿名函數,都保存下了自己閉包變量。 博客原址 理解 Javascript中的this 基于不同的調用方式this的指向也會有所不同,調用方式大致有如下幾種: 調用方式 表達式 構造函數調用 new Foo(); 對象方法...
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
閱讀 1778·2023-04-25 14:33
閱讀 3378·2021-11-22 15:22
閱讀 2177·2021-09-30 09:48
閱讀 2684·2021-09-14 18:01
閱讀 1740·2019-08-30 15:55
閱讀 3005·2019-08-30 15:53
閱讀 2139·2019-08-30 15:44
閱讀 648·2019-08-30 10:58