總結call,apply,bind方法的理解使用和區別。
call,apply,bind這三個方法在JavaScript中是用來改變函數調用的this指向。那么改變函數this指向有什么用呢?我們先來看一段代碼
var a= { name:"harden", fn:function () { console.log(this.name); } } var b = a.fn; a.fn();//harden b();//undefined
調用a.fn方法后得到了harden,但在b方法中我想得到harden,為什么卻是undefined呢?原因是方法在執行的時候才能確定this到底指向誰,實際上this指向的是最終調用函數的對象。這里當b執行時,實際是window調用了fn函數,那么fn中的this就指向window。
在開始講call,apply,bind方法前,一起來總結一下this的指向問題。
總體來說this指向可以概括為一句話:this指向在函數的定義時是不確定的,只有函數執行時才能確定this到底指向誰,實際上this的最終指向的是那個調用它的對象。但是這個說法在函數被很多對象包裹的時候并不成立,請看下面例子。
簡單來說就是:誰(哪個對象)調用的這個函數,那么這個函數中的this就指向這個對象。
例一
function a(){ var name= "harden"; console.log(this.name); //undefined console.log(this); //Window } a();
因為this最終指向調用他的對象,在上述代碼中其實是widow觸發的這個方法,那么this就指向window,window中并沒有定義a,那么就打印出undefined。
例二:
var a = { name:"harden", fn:function() { console.log(this.name);//harden console.log(this);//指向a(可以自己跑一下) } } a.fn()
這里的this指向a,因為這里的fn函數是通過a.fn()執行的,那么this自然指向a。
說到這我就有疑問了,如果我用 window.a.fn()執行函數,this不就指向window了嗎?然后并不是這樣的,請看下一個例子。補充一點:window是js的全局對象。
例三:
var a = { name:"harden", b:{ name:"james", fn:function() { console.log(this.name);//james console.log(this);//指向b } } } a.b.fn()
我們看到最終是a調用的方法,那為什么this會指向b呢?現在總結三句話,來完全理解this的指向問題:
情況一:如果一個函數中有this,但是它沒有被上一級的對象所調用,那么this指向的就是window(除去嚴格模式外)。
情況二:如果一個函數中有this,這個函數有被上一級的對象所調用,那么this指向的就是上一級的對象。
情況三:如果一個函數中有this,這個函數中包含多個對象,盡管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象,例子3可以證明。
構造函數中的this:
function Fn(){ this.name = "harden"; } var a = new Fn(); console.log(a.name); //harden
這里的a可以點出name,因為new關鍵字會改變this的指向。為什么new關鍵字會改變this呢,我自己有兩種看法:
1.在new的過程中會創建一個實例對象,通過apply等方法 通過 Fn.apply({}) 使this指向這個空對象,最后把fn方法中的材料加工完后返回給a。
當this遇到return的時候:
function fn() { this.user = "harden"; return {}; } var a = new fn; console.log(a.user); //undefined function fn() { this.user = "harden"; return function(){}; } var a = new fn; console.log(a.user); //undefined function fn() { this.user = "harden"; return 1; } var a = new fn; console.log(a.user); //harden function fn() { this.user = "harden"; return undefined; } var a = new fn; console.log(a.user); //harden
總結一下:如果返回值是一個對象,那么this指向的就是那個返回的對象,如果返回值不是一個對象那么this還是指向函數的實例。還有一點就是返回null,null也是對象,但是因為他的特殊性,返回后this還是指向函數本身的實例。理解JavaScript中的指向問題
理解完JavaScript中的指向問題,那么回到正題:
1.call
a = { name: "harden" } function b () { console.log(this.name); } b.call(a);//harden b()//undefined
b.call(a)用字面意思來講就是:把函數b添加到對象a的環境中,使函數中的this指向對象a。
call與apply不同的地方就是傳參不同。
2.apply
a = { name: "harden" } function b (data1,data2) { console.log(data1,data2); } b.call(a,"a1","a2");//a1 a2 b.apply(a,["a1","a2"]);//a1 a2
3.bind
a = { name: "harden" } function b () { console.log(this.name); } b.bind(a);//不會執行函數 var aaa = b.bind(a); aaa()//harden
bind不會立即調用函數,是把函數返回,bind通常用它來指定回調函數的this。
關于call, apply, bind方法的區別與內部實現
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104908.html
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
摘要:返回的綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。同時,將第一個參數以外的其他參數,作為提供給原函數的預設參數,這也是基本的顆粒化基礎。 今天想談談一道前端面試題,我做面試官的時候經常喜歡用它來考察面試者的基礎是否扎實,以及邏輯、思維能力和臨場表現,題目是:模擬實現ES5中原生bind函數。也許這道題目已經不再新鮮,部分讀者也會有思路來解答。社區上關于原生bind的研...
摘要:首先,我們判斷是否存在方法,然后,若不存在,向對象的原型中添加自定義的方法。指向調用它的對象。總之三個的使用區別都是用來改變函數的對象的指向的第一個參數都是要指向的對象都可以利用后續參數傳參是返回對應函數,便于稍后調用,是立即調用 apply和call都是為了改變某個函數運行時的上下文而存在的(就是為了改變函數內部this的指向),Function對象的方法,每個函數都能調用; 使用a...
摘要:來自朋友去某信用卡管家的做的一道面試題,用原生模擬的方法,不準用和方法。他們的用途相同,都是在特定的作用域中調用函數。不同之處在于,方法傳遞給調用函數的參數是逐個列出的,而則是要寫在數組中。 本文首發我的個人博客:前端小密圈,評論交流送1024邀請碼,嘿嘿嘿?。 來自朋友去某信用卡管家的做的一道面試題,用原生JavaScript模擬ES5的bind方法,不準用call和bind方法。 ...
閱讀 1784·2021-10-27 14:15
閱讀 3864·2021-10-08 10:12
閱讀 1178·2021-09-22 15:55
閱讀 3238·2021-09-22 15:17
閱讀 844·2021-09-02 15:40
閱讀 1757·2019-08-29 18:33
閱讀 1106·2019-08-29 15:22
閱讀 2361·2019-08-29 11:08