p.s 此文只說setTimeout涌韩。setInterval請如法炮制 肮帐。另,由于本人是新手哼丈,如有錯誤之處還望斧正启妹。
setTimeout的第一個參數(shù)接受一個函數(shù)定義式。
function put(p1,p2){
console.log('put',p1,p2);
}
綁定函數(shù)和傳入?yún)?shù)
setTimeout第一個參數(shù)傳入一個函數(shù)定義式醉旦,第二個參數(shù)傳入延遲時間饶米。至于函數(shù)定義式參數(shù)的傳入方式(準確說是給函數(shù)的參數(shù)們設(shè)置默認值桨啃。并返回這個帶參數(shù)默認值的函數(shù)定義式。)
1.直接使用函數(shù)名檬输,不帶()照瘾,此時表示直接傳入一個定義式。
setTimeout(put,1000);
缺點:不能給put定義式傳參數(shù)
2.外部再包含一個function
setTimeout(function(){
put('some','value');
},1000)
缺點:可讀性不高
優(yōu)點:但最容易理解
3.使用bind傳入?yún)?shù)
setTimeout(put.bind(this,p1,p2),1000);
bind的返回結(jié)果依然是一個函數(shù)定義式丧慈。但能傳入指定的this析命,并傳入指定的參數(shù)。
4.setTimeout余下參數(shù)
setTimeout(put,1000,p1,p2)
就很簡單逃默,在延遲參數(shù)后面繼續(xù)跟參數(shù)就行了鹃愤,全會被算到put函數(shù)上。不過低版本IE似乎不支持
this的問題
setTimeout默認的內(nèi)部this就是window完域,你在一個別的對象里寫個setTimeout直接用this會翻車昼浦。有如下修正方式
var someObj = {
name:'tmh',
intro:'一切為了老玩家',
getIntro:function(){
console.log(this.intro);
},
DelayPutIntro:function(){
setTimeout(/**一個this綁定指向正確的函數(shù)定義式**/,1000);
}
}
1.暴力指向,var self = this;
someObj.DelayPutIntro = function(){
var self = this; // setTimeout外部獲取this筒主,保存在self中
setTimeout(function(){
console.log(self.intro);
},1000)
}
someObj.DelayPutIntro();
2.bind綁定this
someObj.DelayPutIntro = function(){
setTimeout(someObj.getIntro.bind(this,p1,...,pn),1000);
}
someObj.DelayPutIntro();
上文提到過bind可以設(shè)置函數(shù)的參數(shù)默認值关噪,同時也可以改變this指向。第一個參數(shù)用于控制this乌妙,后續(xù)參數(shù)用于綁定默認參數(shù)使兔。
在程序尚未真正執(zhí)行前,此處Bind中出現(xiàn)的this指代的是該function作用域內(nèi)的this藤韵,即somObj虐沥。效果等同于setTimeout(someObj.getIntro.bind(someObj,p1,...,pn),1000)
注:由于bind第一個參數(shù)正確指向了this。所以也能寫成這種形式setTimeout(this.getIntro.bind(this,p1,...,pn),1000);
3.()=>{}箭頭函數(shù)
someObj.DelayPutIntro = function(){
setTimeout(
()=>{console.log(this.intro)},1000);
}
someObj.DelayPutIntro();
或者
someObj.DelayPutIntro = function(){
setTimeout(
()=>{this.getIntro()},1000);
}
someObj.DelayPutIntro();
箭頭函數(shù)語法看ES6泽艘,除了表達更簡便外欲险,還能自動綁定this為定義時而不是使用時。范圍同bind匹涮。
進一步天试,this的范圍
this指向當前作用域的宿主。所以我們使用Bind或者箭頭函數(shù)時然低,作用域是someObj.DelayPutIntro這個函數(shù)喜每,其宿主為someObj。
為了證實this指向當前作用域的宿主
是可靠的雳攘。有如下例子:
var someObj = {
name: 'tmh',
intro: '一切為了老玩家',
getIntro: function () {
console.log(this.intro);
}
}
someObj.DelayPutIntro = function () {
var inner = {
name: '小tmh',
intro: '老玩家算個屁',
getIntro: function () {
console.log(this.intro);
},
DelayPutIntro: function () {
setTimeout(this.getIntro.bind(this), 1000);
}
}
inner.DelayPutIntro();
}
someObj.DelayPutIntro();
注意觀察我們在someObj.DelayPutIntro函數(shù)中再創(chuàng)建了一個Inner對象带兜。那么這段代碼中setTimeout里函數(shù)定義式綁定的this應(yīng)該指向什么?
是的吨灭,該this的作用域是inner.DelayPutIntro這個函數(shù)刚照,故而this指向其宿主Inner,打印的結(jié)果也是inner的intro而不是someObj的intro了。
關(guān)于js對象喧兄,作用域无畔,作用域鏈還有this指向的問題還有很多啊楚。此處不鋪開闡述了。
總結(jié)一下
函數(shù)綁定及參數(shù)綁定
- 直接填寫函數(shù)名傳入不帶參的定義式
- 外套一個function/或者()=>{}箭頭函數(shù)檩互,內(nèi)部寫一個傳入了參的函數(shù)引用特幔。
- xx.bind(this,...porps)返回一個xx改造后的新函數(shù)咨演,該函數(shù)經(jīng)由bind綁定了新的參數(shù)默認值
- setTimeout(put,1000,p1,p2,...,pn)闸昨,直接在setTimeout的規(guī)定參數(shù)后面跟新參數(shù),將綁到put上
this
- bind綁定
- 箭頭函數(shù)綁定
- var self = this;暴力指向