詳解JavaScript中的this硬綁定
一、this顯示綁定
this顯示綁定,顧名思義,它有別于this的隱式綁定,而隱式綁定必須要求一個對象內(nèi)部包含一個指向某個函數(shù)的屬性(或者某個對象或者上下文包含一個函數(shù)調(diào)用位置),并通過這個屬性間接調(diào)用這個函數(shù),從而把this簡介/隱式綁定到這個對象上。但是this的隱式綁定存在一個綁定對象丟失問題,如下面代碼所示:
function afun() { console.log(this.a); } var obj = { a: 1, afun: afun }; var a = "hello"; setTimeout(obj.afun, 100);//"hello"
出人意料的是,控制臺打印出來的結果是全局變量a的結果,而不是擁有指向函數(shù)屬性的對象的a的值,這就是隱式綁定的對象丟失,回調(diào)函數(shù)丟失綁定對象是非常常見的。
但是,顯示綁定仍然不能解決綁定對象丟失的問題,但是顯示綁定的一個變種,即硬綁定可以解決綁定對象丟失。
在此之前,我們先來看看什么是顯示綁定。
我們可以通過使用函數(shù)的call()和apply()方法實現(xiàn)this顯示綁定,絕大多數(shù)內(nèi)置函數(shù)和自定義函數(shù)都可以調(diào)用這兩種方法。他們均接收兩個參數(shù)
參數(shù):
thisArg
: 要綁定到調(diào)用者this的對象。
arg1, arg2, ...
(call):指定的參數(shù)列表,即要傳給調(diào)用者的參數(shù)。比如a.call(obj, args)/a.apply(obj, args),args為參數(shù)傳給調(diào)用者函數(shù)a作為該函數(shù)的實參。
argsArray
(apply):一個數(shù)組或者類數(shù)組對象,如果該參數(shù)的值為 null 或 undefined,則表示不需要傳入任何參數(shù)。
返回值
:調(diào)用者函數(shù)若有返回值則返回該值,沒有返回值則返回undefined。
來看下面的代碼:
function bfun() { return this.a; } var obj1 = { a: "hello" }; console.log(bfun.apply(obj1), bfun.call(obj1));//"hello" "hello"
若傳入的第一個參數(shù)時一個原始值呢?來看下面的代碼:
function bfun() { return this; } console.log(bfun.apply(3));//[Number: 2]
沒錯,原始值被轉換成了它的對象形式,也就是new Number(),這被成為"裝箱"。
但是,我們前面提到過,this顯示綁定雖然強大,但是仍然不能解決this綁定丟失問題。下面我們來解釋硬綁定,即顯示綁定的一個變種,它能完美解決this綁定丟失問題。
二、硬綁定
先來看看下面的代碼:
function cfun() { console.log(this.a)//"hello" return this.a; } var obj2 = { a: "hello" }; var fn = function() { return cfun.apply(obj2); }; console.log(fn());//"hello" setTimeout(fn, 100);//"hello"
可以看到,硬綁定確實解決了this綁定丟失,但值得注意的是,通過apply()綁定的this對象,無法二次更改綁定對象:
function f() { console.log( this.a ); } var obj = { a:2 }; var b = function() { f.call( obj ); }; b(); // 2 b.call( window ); // 2
硬綁定的一個典型應用場景是創(chuàng)建一個包裹函數(shù),傳入所有的參數(shù)給調(diào)用者函數(shù)并返回接收到的所有值。
function dfun(v) { return (v[0] + this.a); } var obj3 = { a: 10 }; var fn1 = function() { return dfun.call(obj3, arguments); } var result = fn1(6); console.log(result);//16
對于arguments而言,call()和apply()的不同之處在于他們的參數(shù)類型不同:
function efun(v) { console.log(..v)//6 10 11 return (v); } var obj4 = { a: 10 }; var fn1 = function() { return efun.apply(obj3, arguments); } var result = fn1([6, 10, 11]); console.log(result);//[6, 10, 11]
也就是說call()的參數(shù)類型是Object,它傳入的參數(shù)列表會被轉換為鍵為'0'(隨傳入?yún)?shù)數(shù)量遞增),值為傳入?yún)?shù)的對象;而apply()的參數(shù)類型則是數(shù)組或者類數(shù)組。
function dfun(v) { return (v); } var obj3 = { a: 10 }; var fn1 = function() { return dfun.call(obj3, arguments); } var result = fn1(6, 19, 1, 1); console.log(result);//[Arguments]{'0':6,'1':19,2':1,3':1} console.log(typeof result);//'object'
最強大的一種方法是將包裹函數(shù)創(chuàng)建為可以重復使用的輔助函數(shù),封裝可重復使用的硬綁定。
function ffun(v) { return this.a * v; } var obj5 = { a: 5, }; var fn2 = function(fn, obj) { return function() { return fn.apply(obj, arguments); } } var bind = fn2(ffun, obj5); console.log(bind(10));//50
由于硬綁定十分常用,但通過包裹函數(shù)創(chuàng)建可重復使用的硬綁定比較麻煩,所以ES5提供了一個實現(xiàn)相同功能的方法bind()。用法如下:
function hfun(v) { return this.a * v; } var obj6 = { a: 6 }; var bind = hfun.bind(obj6); console.log(bind(4));//24
可以看到,我們再無需構建一個包裹函數(shù)來手動調(diào)用call或apply方法,只需要提供調(diào)用者和綁定到調(diào)用者this的對象即可。
我們可能發(fā)現(xiàn)了一個奇怪的現(xiàn)象,通過apply()和call()方法綁定的對象在傳參給調(diào)用者時,需要設置一個參數(shù)占位,但bind()方法則不用,這是因為他們的返回值不同,bind()方法會返回一個經(jīng)過硬編碼的新函數(shù),它會把傳入?yún)?shù)設置為this的上下文并調(diào)用原始函數(shù)。可以理解bind使用方法為bind(obj)(args)
。而對于call()和apply()方法而言,一旦調(diào)用此方法,就會立刻返回調(diào)用者函數(shù)的返回值,所以此時就需要同時傳入?yún)?shù)給方法的參數(shù)占用符,然后被函數(shù)參數(shù)讀取。值得注意的是,bind方法的參數(shù)和call方法類似。
到此這篇關于詳解JavaScript中的this硬綁定 的文章就介紹到這了,更多相關JavaScript this硬綁定 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- 一文全面解析JS中的this綁定規(guī)則
- JavaScript中this綁定規(guī)則你理解了嗎
- 細說JavaScript中的this指向與綁定規(guī)則
- JavaScript this綁定與this指向問題的解析
- JavaScript?中的?this?綁定規(guī)則詳解
- JavaScript中this的綁定你知道幾種?
- 一文搞懂JavaScript中的this綁定規(guī)則
- JavaScript中?this?的綁定指向規(guī)則
- 詳解JavaScript的this指向和綁定
- JavaScript this綁定過程深入詳解
- React.js綁定this的5種方法(小結)
- JavaScript調(diào)用模式與this關鍵字綁定的關系
- 深入理解JavaScript this綁定規(guī)則
相關文章
簡單聊聊JavaScript中作用域與自執(zhí)行函數(shù)的使用
作用域指的是一個變量的作用范圍,自執(zhí)行函數(shù)是指定義后立即執(zhí)行的函數(shù),它可以被用來創(chuàng)建一個私有作用域,本文主要來和大家聊聊二者的具體定義與使用,感興趣的可以了解下2024-03-03JavaScript地圖拖動功能SpryMap的簡單實現(xiàn)
SpryMap是一個獨立的并且是輕量級的JavaScript類庫,它不依賴于任何其他的JS框架2013-07-07JavaScript talbe表中指定位置插入一行的實現(xiàn)代碼 腳本之家修正版
用js實現(xiàn)的在table中指定的位置插入一行,先點一下表中你想插入的位置,點擊即可。2009-06-06