背景
我有一个原型对象,它有许多函数可以从这样的列表中访问信息:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
'this.type'应该来自在函数中分配原型的对象:
function accessor(type) {
var widget = Object.create(prototype_object);
widget.type = type;
return widget;
}
我有一份中央信息清单,现在我可以致电:
var access_foo = accessor('foo'); // Create the accessor
access_foo.green(list); //Find 'foo_green' in the list
问题
这些访问者fxns被传递到应用程序的不同区域,并在分配给新对象后被调用。因此原型函数中的'this'被重新分配(正如javascript中预期的那样)并导致未定义的类型。
“CALL IT”:调用将要求我将原始访问者作为'this'传递,但正如我所说,access_foo.green会在应用程序的其他位置传递,并且无法在调用时引用回access_foo。
“更改PROTOTYPE_OBJECT PARAMS”:不是应用程序编写方式的选项。
最后,我需要一个知道其类型的对象,并共享对大量函数的访问权限。我是否正确地说,没有办法创建可以在上下文之外调用的自定义访问器,而无需将它们全部实例化/绑定到完整的可能原型函数集?
答案 0 :(得分:1)
您似乎排除了所有可能的解决方案。如果您需要解决方案,则必须适应其中一个选项。如果您在许多地方传递访问者功能,并希望它们永久地绑定到您的对象(因此您不必同时传递该对象),那么您将不得不改变您的方式做事。
最干净的方法是在构造函数中定义方法,并让方法使用构造函数局部变量作为对象引用,并依赖构造函数闭包而不是this
。然后,即使this
错误,他们仍然会工作。您必须重做如何创建对象才能执行此操作。
您还可以重新定义所有方法以预先绑定自己。我将展示两种选项的代码示例。
这是关闭方法:
function myObj() {
var self = this;
self.prop1 = "foo";
// define all methods in here and use self instead of this
self.method1 = function() {
console.log(self.prop1);
}
}
var x = new myObj();
var m = x.method1;
m();
而且,这是预绑定方法,同时尽可能少地更改现有代码:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
function accessor(type) {
var widget = Object.create(prototype_object);
widget.type = type;
// reassign prototype methods to the actual object and make them pre-bound
// to this particular instance
for (var method in prototype_object) {
if (typeof method === "function") {
// assign pre-bound method to the instance
widget[method] = widget[method].bind(widget);
}
}
return widget;
}
这个是前一个版本的一个更优化的版本,它根本没有将新方法放在原型上:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
function accessor(type) {
var widget = {};
widget.type = type;
// reassign prototype methods to the actual object and make them pre-bound
// to this particular instance
for (var method in prototype_object) {
if (typeof method === "function" && prototype_object.hasOwnProperty(method)) {
// assign pre-bound method to the instance
widget[method] = prototype_object[method].bind(widget);
}
}
return widget;
}