在平時對setTimeout
addEventListener
這種函數(shù)的使用,都會傳入一個匿名的callback函數(shù)
如:
1.
window.setTimeout(function() {
console.log(this)
}, 1000)
或者
2.
var el = document.getElementById('wrapper')
el.addEventListener('click', function() {
console.log(this)
}, false)
上述情況1中this
會指向setTimeout
函數(shù)的caller -> window對象
而情況2中this
也會指向addEventListener
函數(shù)的caller -> wrapper這個對象
但是我自己類似于window.setTimeout
這樣創(chuàng)建了一個對象
var a = {
b: 'b in a',
c: function (callback) {
callback()
}
}
//調用a對象的c函數(shù),傳入匿名函數(shù)作為參數(shù)
a.c(function() {
//本以為this是指向a的,會輸出字符串'b in a',實際此時this指向window
console.log(this.b)
})
我原本以為會類似于window.setTimeout
el.addEventListener
那樣,this會指向.
(點號)之前的對象。
然后我改了一下對象a
var a = {
b: 'b in a',
c: function (callback) {
callback.bind(this)()
}
}
這個時候this才指向a。
那么問題來了:
1.像這種匿名函數(shù)傳參的用法,為什么使用我自己定義的對象和瀏覽器提供的api產生的效果不一樣呢?這種類型的this的指向應該如何更好的理解?
2.是不是像setTimeout
、addEventListener
這種系統(tǒng)api,它的內部實現(xiàn)就幫我們去把this
bind給了調用這個方法的對象,如setTimeout
中就有callback.bind(window)
和addEventListener
就有callback.bind(el)
?
有沒有各路大神可以解答一下,小弟感激不盡。
你可以把this當做function的一個隱藏參數(shù),相當于
function(_this, otherArgs){
}
事實上基本所有語言也都是這么處理的。所以當this不對的時候,可以用bind顯性地傳遞這個參數(shù)。
檢查一個function是否綁定了this這個參數(shù)可以用下面的方法:
// ES5
function isBindable(func) {
return func.hasOwnProperty('prototype');
}
// ES6
const isBindable = func => func.hasOwnProperty('prototype');
事件監(jiān)聽那里可能是做了特殊處理,畢竟JS是個設計糟糕的語言(哈)
關于this的指向的優(yōu)先級
new Foo()
綁定新對象bind/call/apply
綁定指定的對象綁定上下文
var a = {
b: function () {
//this -> a
}
}
var a = {
b: 'b in a',
c: function c2(callback) {
callback()
}
}
//調用a對象的c函數(shù),傳入匿名函數(shù)作為參數(shù)
a.c(function c1() {
//c1里的this是什么,首先排除規(guī)則1,2,其次在c2函數(shù)作用域執(zhí)行,排除3,使用默認規(guī)則。
console.log(this.b)
})
那么樓主的代碼,為了描述我命了名。
以下為一段為了瀏覽器兼容而提供的polyfill
代碼
這段代碼結合上述規(guī)則可以很清楚的說明addEventListener
的this
(function() {
if (!Event.prototype.preventDefault) {
Event.prototype.preventDefault=function() {
this.returnValue=false;
};
}
if (!Event.prototype.stopPropagation) {
Event.prototype.stopPropagation=function() {
this.cancelBubble=true;
};
}
if (!Element.prototype.addEventListener) {
var eventListeners=[];
var addEventListener=function(type,listener /*, useCapture (will be ignored) */) {
var self=this;
var wrapper=function(e) {
e.target=e.srcElement;
e.currentTarget=self;
if (typeof listener.handleEvent != 'undefined') {
listener.handleEvent(e);
} else {
listener.call(self,e);
}
};
if (type=="DOMContentLoaded") {
var wrapper2=function(e) {
if (document.readyState=="complete") {
wrapper(e);
}
};
document.attachEvent("onreadystatechange",wrapper2);
eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper2});
if (document.readyState=="complete") {
var e=new Event();
e.srcElement=window;
wrapper2(e);
}
} else {
this.attachEvent("on"+type,wrapper);
eventListeners.push({object:this,type:type,listener:listener,wrapper:wrapper});
}
};
var removeEventListener=function(type,listener /*, useCapture (will be ignored) */) {
var counter=0;
while (counter<eventListeners.length) {
var eventListener=eventListeners[counter];
if (eventListener.object==this && eventListener.type==type && eventListener.listener==listener) {
if (type=="DOMContentLoaded") {
this.detachEvent("onreadystatechange",eventListener.wrapper);
} else {
this.detachEvent("on"+type,eventListener.wrapper);
}
eventListeners.splice(counter, 1);
break;
}
++counter;
}
};
Element.prototype.addEventListener=addEventListener;
Element.prototype.removeEventListener=removeEventListener;
if (HTMLDocument) {
HTMLDocument.prototype.addEventListener=addEventListener;
HTMLDocument.prototype.removeEventListener=removeEventListener;
}
if (Window) {
Window.prototype.addEventListener=addEventListener;
Window.prototype.removeEventListener=removeEventListener;
}
}
})()
北大青鳥APTECH成立于1999年。依托北京大學優(yōu)質雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網學院和江蘇省首批服務外包人才培訓基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團創(chuàng)建于1999年,經過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術與教育服務機構,發(fā)展為教育服務業(yè)的綜合性企業(yè)集團,成為集合面授教學培訓、網
達內教育集團成立于2002年,是一家由留學海歸創(chuàng)辦的高端職業(yè)教育培訓機構,是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
曾工作于聯(lián)想擔任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔任項目經理從事移動互聯(lián)網管理及研發(fā)工作,曾創(chuàng)辦藍懿科技有限責任公司從事總經理職務負責iOS教學及管理工作。
浪潮集團項目經理。精通Java與.NET 技術, 熟練的跨平臺面向對象開發(fā)經驗,技術功底深厚。 授課風格 授課風格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網頁制作和網頁游戲開發(fā)。
具有10 年的Java 企業(yè)應用開發(fā)經驗。曾經歷任德國Software AG 技術顧問,美國Dachieve 系統(tǒng)架構師,美國AngelEngineers Inc. 系統(tǒng)架構師。