bind()、call()、apply()理解及用法
apply和call都是為了改變某個(gè)函數(shù)運(yùn)行時(shí)的上下文而存在的(就是為了改變函數(shù)內(nèi)部this的指向),Function對象的方法,每個(gè)函數(shù)都能調(diào)用;
使用apply或call方法,其運(yùn)行的上下文指向第一個(gè)參數(shù),apply的第二個(gè)參數(shù)是一個(gè)參數(shù)數(shù)組,call的第二個(gè)及其以后的參數(shù)都是數(shù)組里面的元素。
apply和call的常用用法:
數(shù)組之間的追加;
例如:多維數(shù)字轉(zhuǎn)一維
let arr=[1,[7,8],[5,6]];res=[].concat.apply([],arr)擴(kuò)充作用域擁有Math的min和max方法,獲取數(shù)組中的最大值和最小值;
let numbers = [5, 458 , 120 , -215 ];
let maxInNumbers = Math.max.apply(Math, numbers), //458
驗(yàn)證是否是數(shù)組;
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]' ;}
比如: arguments對象,獲取到的文檔節(jié)點(diǎn)等,并沒有數(shù)組的那些方法:
Array.prototype.slice.apply(argument);
//理論上來說這個(gè)比較快,直接在原型上查找slice方法
//但實(shí)際上比較慢
或者
[].slice.apply(arguments);
//理論上來說這個(gè)比較慢,因?yàn)橐狝rray做一個(gè)實(shí)例化再查找slice方法
//實(shí)際上比較快,因?yàn)楝F(xiàn)在的各種自動(dòng)化工具會(huì)把上一種方法轉(zhuǎn)換為這種,而第二種代碼比較簡潔,所以會(huì)比較快;
binde 方法的使用
也是改變函數(shù)體內(nèi)this的指向,bind()是es5中的方法,bind會(huì)創(chuàng)建一個(gè)新函數(shù),稱為綁定函數(shù),當(dāng)調(diào)用這個(gè)函數(shù)的時(shí)候,綁定函數(shù)會(huì)以創(chuàng)建它時(shí)傳入bind()方法的第一個(gè)參數(shù)作為this,傳入bind()方法的第二個(gè)及以后的參數(shù)加上綁定函數(shù)運(yùn)行時(shí)本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù);
例如:(后面的代碼皆取自張鑫旭大神的博客)
但由于ie6~ie8不支持該方法,所以若想在這幾個(gè)瀏覽器中使用,我們就要模擬該方法,這也是面試常考的問題,模擬的代碼如下:
if (!function() {}.bind) {Function.prototype.bind = function(context) {var self = this;var args = Array.prototype.slice.call(arguments);return function() {return self.apply(context, args.slice(1)); }}; }上面的代碼中this的指向是個(gè)容易理解錯(cuò)的地方。
首先,我們判斷是否存在bind方法,然后,若不存在,向Function對象的原型中添加自定義的bind方法。
這里面var self = this這段代碼讓我很困擾,按理說,prototype是一個(gè)對象,對象的this應(yīng)該指向?qū)ο蟊旧?#xff0c;也就是prototype,但真的是這樣嗎。看看下面的代碼:
function a(){};a.prototype.testThis = function(){console.log(a.prototype == this);};var b = new a();b.testThis();//false顯然,this不指向prototype,而經(jīng)過測試,它也不指向a,而指向b。所以原型中的this值就明朗了。指向調(diào)用它的對象。
Array.prototype.slice.call(arguments);上面這段代碼,它的作用是將一個(gè)類數(shù)組轉(zhuǎn)化為真正的數(shù)組,arguments是傳給call的那個(gè)上下文(由于arguments自己沒有slice方法,這里屬于借用Array原型的slice方法)。而且經(jīng)過測試,若果你不給slice傳參數(shù),那就等于傳了個(gè)0給它,結(jié)果就是返回一個(gè)和原來數(shù)組一模一樣的副本。
這之后的代碼就很好理解,返回一個(gè)函數(shù),該函數(shù)把傳給bind的第一個(gè)參數(shù)當(dāng)做執(zhí)行上下文,由于args已經(jīng)是一個(gè)數(shù)組,排除第一項(xiàng),將之后的部分作為第二部分參數(shù)傳給apply,前面講過apply的用法。
如此,我們自己的這個(gè)bind函數(shù)的行為就同es5中的bind一樣了。
總之三個(gè)的使用區(qū)別:
- 都是用來改變函數(shù)的this對象的指向的;
- 第一個(gè)參數(shù)都是this要指向的對象;
- 都可以利用后續(xù)參數(shù)傳參;
- bind是返回對應(yīng)函數(shù),便于稍后調(diào)用,apply、call是立即調(diào)用;
總結(jié)
以上是生活随笔為你收集整理的bind()、call()、apply()理解及用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习Python最好的途径——激发自己的
- 下一篇: thymeleaf