[英]Calling a function in javascript object literal notation declaration
我正在嘗試使用this
關鍵字調用我創建的對象文字中的函數。 但是錯誤顯示出這個this.doTheMove()
不是函數:
window.onload = function(){
var animBtn = document.getElementById('startAnim');
animBtn.addEventListener('click', Animation.init, false);
}
var Animation = {
init: function(){
this.doTheMove(); // I'm calling the function here, but it gives an error.
},
doTheMove: function(){
alert('Animation!');
}
}
為什么會出錯?
對正在發生的事情的解釋。 Pointy的答案很好,但我想更一般地解釋它。 可以在這里找到關於this
非常好的研究
事件處理程序只是一個回調。 你傳遞一個函數和一個事件來監聽。 它所做的一切就是調用該函數。
Animation.init只是該函數的一個getter。 可以這樣想:
var callback = Animation.init
animBtn.addEventListener('click', callback, false);
...
// internal browser event handler
handler() {
// internal handler does stuff
...
// Oh click event happened. Let's call that callback
callback();
}
所以你所做的就是傳入
var callback = function(){
this.doTheMove(); // I'm calling the function here, but it gives an error.
}
默認情況下在javascript this === window
。 如果沒有設置為某個東西,這將引用全局對象。 凈效果是window.doTheMove
被調用。 而且這個功能不存在。
在這種情況下,由於callback
是由事件處理程序調用的,因此this
對象指向觸發事件的DOM對象,因此您的調用node.doTheMove
仍然不存在。
你想要做的是用動畫引用它。
var callback = function() {
Animation.init();
}
這是一個函數執行,它在Animation
上執行init
。 當你在這樣的對象上執行它然后在內部this === Animation
就像你期望的那樣。
總結一下。 這里的問題是Animation.init
只是對函數的引用。 它沒有像Pointy提到的任何其他信息。
你必須改變你設置的方式:
window.onload = function(){
var animBtn = document.getElementById('startAnim');
animBtn.addEventListener('click', function() { Animation.init(); }, false);
}
在JavaScript中,函數恰好被定義為對象文字的一部分的事實實際上並不是非常重要(事實上,如果有的話)。 對Animation.init
的引用確實可以使您獲得正確的函數,但問題是當稍后調用該函數時(響應實際的“點擊”),瀏覽器調用該函數但不知道對象“動畫” “應該是this
參考。 同樣,函數被聲明為對象的一部分這一事實在這里根本不重要。 因此,如果您希望this
是您自己選擇的特定內容,那么您必須確保在您控制的代碼中明確設置它。 上面的解決方案是關於最簡單的方法:它使用匿名函數處理“click”事件,除了通過“Animation”通過顯式引用調用“init”函數之外什么都不做。 這將確保在“init”運行時this
引用“Animation”對象。
另一種方法是使用某些瀏覽器和框架支持的“.bind()”工具:
window.onload = function(){
var animBtn = document.getElementById('startAnim');
animBtn.addEventListener('click', Animation.init.bind(Animation); }, false);
}
凈效果幾乎完全相同:對“.bind()”的調用返回一個函數,該函數調用它所調用的函數(即“Animation”對象中的“init”函數),並且它的第一個參數是this
引用(“context”對象)。 這與我們從第一個例子得到的相同,或者無論如何都是有效的。
我想這是另一種不錯的方法。
window.onload = function(){
var animBtn = document.getElementById('startAnim');
animBtn.addEventListener('click', Animation.init, false);
};
var Animation = {
init: function(){
Animation.doTheMove(); // This will work, but your IDE may complain...
},
doTheMove: function(){
alert('Animation!');
}
};
六年半之后,我希望我的回答也能為當前和未來的開發者提供一些見解。
我傾向於使用自定義函數內部的文字對象進行編碼,如果添加了另一個自執行函數以及try和catch語句,則發布的原始問題可以正常工作。
指出它是關於范圍和背景的非常重要。
請更正任何缺點或提供使用此方法的更有效建議。
(function() {
console.log(this); // window object
var animation = {
init: function() {
this.doTheMove();
},
doTheMove: function() {
alert("Animation");
console.log(animation); // animation object
}
};
(function() {
try {
console.log("animation.init"); // animation.init function
animation.init();
} catch(e) {
console.log("Error is: " + e);
}
})();
})();
您可能希望使用portotype基本方法:
// generate a prototype object which can be instantiated
var Animation = function() { this.doTheMove(); }
Animation.prototype.doTheMove = function() {
// if the object has only one method, the whole code could be moved to
// var Animation = function() {...} above
alert('Animation!');
}
Animation.prototype.otherMethod = function(param1, param2) {
// ...
}
// run the code onload
window.onload = function(){
var animBtn = document.getElementById('startAnim');
animBtn.addEventListener('click', new Animation(), false);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.