我正在研究BackboneJS模块。在视图中,我将插件应用于当前元素。我正在传递一个选项对象setOptions
,它被设置为当前视图的属性。在这个对象中,我也调用了一个函数this.foo
。但它给了我以下错误:foo of undefined
。以下是我的代码。
var b = Backbone.View.extend({
setOptions: {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
callback: this.foo // this returns foo of undefined
},
initialize: function () {
this.setPlugin();
},
setPlugin: function () {
this.$el.pluginName(this.setOptions);
},
foo: function () {
console.log('FOO');
}
});
为了解决这个问题,我写了一个函数setOptions
。并返回设置插件选项的对象文字。这次函数this.foo
成功调用,但在foo
中this
的引用指向this.$el
。 我希望此关键字指向当前模块而不是该元素。我需要这个,因为我想在foo
内调用更多函数,但我不能更改此关键字的引用。 我该怎么做?
下面是我的第二次尝试代码
var b = Backbone.View.extend({
initialize: function () {
this.setPlugin();
},
setPlugin: function () {
this.$el.pluginName(this.setOptions());
},
setOptions: function () {
return {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
callback: this.foo
}
},
foo: function () {
// here "this" reference to this.$el but not current module
console.log('FOO');
}
});
答案 0 :(得分:0)
问题是,在创建对象之前,您无法从同一对象引用对象的属性。因此,在构造视图对象并且它到达行callback: this.foo
的情况下,在对象中尚未创建此类属性。因此错误。
最简单的解决方法是使用getter函数:
setOptions: function() {
return {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
callback: _.bind(this.foo, this)
}
},
并像这样使用它:
setPlugin: function () {
this.$el.pluginName(this.setOptions());
},
答案 1 :(得分:0)
以下是发生的事情(查看评论):
// Fake "plugin" function.
function pluginName(options) {
// Here I'm setting the 'this' value of 'foo' to the document body.
options.callback.call(document.body);
// Here the 'this' value would be the 'options' object because I'm calling
// the method through the 'options' object itself.
/* options.callback(); */
// If I did the following instead, the 'this' value of 'foo' would
// be the global object, which is the 'window' object. That's because
// any function that's not called by a specific object is automatically
// executed in the context of the 'window' object.
// var fn = options.callback;
/* fn(); */
}
var view = {
initialize: function () {
this.setPlugin();
},
setPlugin: function () {
pluginName(this.setOptions());
},
setOptions: function () {
return {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
// 'foo' here is called by the plugin, and its
// 'this' value depends on how the plugin calls it.
callback: this.foo
}
},
foo: function () {
console.log('FOO');
// The 'this' value here depends on how the plugin calls 'foo'; in this example it is the document body.
console.log(this);
}
};
这是一个修复:
// Fake "plugin" function.
function pluginName(options) {
options.callback.call(document.body);
}
var view = {
initialize: function () {
this.setPlugin();
},
setPlugin: function () {
pluginName(this.setOptions());
},
setOptions: function () {
return {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
// The 'bind' method creates an other callback for you, by making
// the 'this' value equal to whatever you pass it as the first argument.
callback: this.foo.bind(this) // or use Underscore's '_.bind()' method as mentioned below.
}
},
foo: function () {
console.log('FOO');
console.log(this); // 'this' here is the 'view' object.
}
};
这是另一个修复:
// Fake "plugin" function.
function pluginName(options) {
options.callback.call(document.body);
}
var view = {
initialize: function () {
this.setPlugin();
},
setPlugin: function () {
pluginName(this.setOptions());
},
setOptions: function () {
var self = this;
return {
opt1: 'Option 1',
opt2: 'Option 2',
opt3: 'Option 3',
opt4: 'Option 4',
// Similar to the 'bind' method but manually.
callback: function() {
self.foo();
}
}
},
foo: function () {
console.log('FOO');
console.log(this); // 'this' here is the 'view' object.
}
};