采用我正在尝试的这个非常简单的框架(这样我就可以更深入地学习JavaScript的函数原型。)
(function(){
var app = {
ui: {
app: document.querySelector('.app'),
settings: document.querySelector('.settings'),
},
actions: 'click settings openSidebar'
,
functions: {
openSidebar: function(e){
console.log(this); // <- expected value of this is 'app.ui'
}
},
run: function(){
var a1 = this.actions.split("\n");
var a2 = this.actions.split(" ");
var self = this;
this.ui[a2[1]].addEventListener(a2[0], function(e){
app.functions.openSidebar.call(self.ui,e);
});
}
};
app.run();
})();
这很有效。控制台的输出是:
Object {ui: Object, actions: "click settings openSidebar", functions: Object, run: function}
然而,当我尝试这样做时:
var self = this;
this.ui[a2[1]].addEventListener(a2[0], function(e){
app.functions.openSidebar(e);
}.bind(this));
this
中openSidebar()
的上下文是openSidebar(又名绑定无效)。控制台输出:
Object {openSidebar: function}
但是,当我尝试使用apply
函数时,如下所示:
app.functions.openSidebar.apply(self.ui,e);
一切正常(openSidebar中的this
为app.ui
)除了参数(e
)没有通过外,所以e == undefined
。
这里是:
1。为什么在第一个例子中没有绑定工作(根本没有)?
2。为什么在没有传递参数的情况下应用工作(e
(事件))?
添加布朗尼点:
第3。为什么呼叫按预期工作?
答案 0 :(得分:1)
您需要这样做:
this.ui[a2[1]].addEventListener(a2[0], app.functions.openSidebar.bind(this));
bind返回一个新函数,其中包含您传入的任何内容的手动设置上下文。因为您没有在正确的函数上使用bind,所以您在调用的左侧使用app.functions
调用函数函数,此后在调用函数中称为this
!
Apply将参数作为数组,而不是命名参数......
我不能解释第三个,而不是说呼叫是如何工作的!
答案 1 :(得分:1)
为什么在第一个例子中没有绑定工作(根本没有)?
它“有效”,它没有按照你的期望做到。
您的匿名函数this
内部确实是bind
设置的值。但是,当您调用同时也是对象属性(functions.openSidebar
)的函数时,对于该调用this
会自动绑定到函数内的该对象(即this === functions
)。来自父上下文的this
的值永远不会在调用链中“继承”。
为什么在没有传递参数的情况下应用工作(
e
(事件))?
因为apply
试图通过将其视为数组来从其自己的第二个参数e
中提取调用的参数。这意味着首先检查其length
属性;您的事件对象没有length
,因此apply
会生成undefined
值,并且有效地表现得像传入一个空数组一样。请参阅annotated ES5 reference for the details。
为什么呼叫按预期工作?
这是一个奇怪的问题。为什么不有效?你正在使用它,就像它的用途一样。