<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
this顯示繫結,顧名思義,它有別於this的隱式繫結,而隱式繫結必須要求一個物件內部包含一個指向某個函數的屬性(或者某個物件或者上下文包含一個函數呼叫位置),並通過這個屬性間接呼叫這個函數,從而把this簡介/隱式繫結到這個物件上。但是this的隱式繫結存在一個繫結物件丟失問題,如下面程式碼所示:
function afun() { console.log(this.a); } var obj = { a: 1, afun: afun }; var a = "hello"; setTimeout(obj.afun, 100);//"hello"
出人意料的是,控制檯列印出來的結果是全域性變數a的結果,而不是擁有指向函數屬性的物件的a的值,這就是隱式繫結的物件丟失,回撥函數丟失繫結物件是非常常見的。
但是,顯示繫結仍然不能解決繫結物件丟失的問題,但是顯示繫結的一個變種,即硬繫結可以解決繫結物件丟失。
在此之前,我們先來看看什麼是顯示繫結。
我們可以通過使用函數的call()和apply()方法實現this顯示繫結,絕大多數內建函數和自定義函數都可以呼叫這兩種方法。他們均接收兩個引數
引數:
thisArg
: 要繫結到呼叫者this的物件。
arg1, arg2, ...
(call):指定的參數列,即要傳給呼叫者的引數。比如a.call(obj, args)/a.apply(obj, args),args為引數傳給呼叫者函數a作為該函數的實參。
argsArray
(apply):一個陣列或者類陣列物件,如果該引數的值為 null 或 undefined,則表示不需要傳入任何引數。
返回值
:呼叫者函數若有返回值則返回該值,沒有返回值則返回undefined。
來看下面的程式碼:
function bfun() { return this.a; } var obj1 = { a: "hello" }; console.log(bfun.apply(obj1), bfun.call(obj1));//"hello" "hello"
若傳入的第一個引數時一個原始值呢?來看下面的程式碼:
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
硬繫結的一個典型應用場景是建立一個包裹函數,傳入所有的引數給呼叫者函數並返回接收到的所有值。
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()的不同之處在於他們的引數型別不同:
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()的引數型別是Object,它傳入的參數列會被轉換為鍵為'0'(隨傳入引數數量遞增),值為傳入引數的物件;而apply()的引數型別則是陣列或者類陣列。
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'
最強大的一種方法是將包裹函數建立為可以重複使用的輔助函數,封裝可重複使用的硬繫結。
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
由於硬繫結十分常用,但通過包裹函數建立可重複使用的硬繫結比較麻煩,所以ES5提供了一個實現相同功能的方法bind()。用法如下:
function hfun(v) { return this.a * v; } var obj6 = { a: 6 }; var bind = hfun.bind(obj6); console.log(bind(4));//24
可以看到,我們再無需構建一個包裹函數來手動呼叫call或apply方法,只需要提供呼叫者和繫結到呼叫者this的物件即可。
我們可能發現了一個奇怪的現象,通過apply()和call()方法系結的物件在傳參給呼叫者時,需要設定一個引數佔位,但bind()方法則不用,這是因為他們的返回值不同,bind()方法會返回一個經過寫死的新函數,它會把傳入引數設定為this的上下文並呼叫原始函數。可以理解bind使用方法為bind(obj)(args)
。而對於call()和apply()方法而言,一旦呼叫此方法,就會立刻返回撥用者函數的返回值,所以此時就需要同時傳入引數給方法的引數佔用符,然後被函數引數讀取。值得注意的是,bind方法的引數和call方法類似。
到此這篇關於詳解JavaScript中的this硬繫結 的文章就介紹到這了,更多相關JavaScript this硬繫結 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45