在Javascript中将对象原型函数绑定到对象

时间:2015-02-20 20:14:01

标签: javascript prototype call this bind

背景

我有一个原型对象,它有许多函数可以从这样的列表中访问信息:

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中预期的那样)并导致未定义的类型。

“SO BIND IT”:我们可以绑定到函数来设置'this'来创建新函数。我无法在几十个地方为100多种对象类型实例化60个新函数。

“CALL IT”:调用将要求我将原始访问者作为'this'传递,但正如我所说,access_foo.green会在应用程序的其他位置传递,并且无法在调用时引用回access_foo。

“更改PROTOTYPE_OBJECT PARAMS”:不是应用程序编写方式的选项。

最后,我需要一个知道其类型的对象,并共享对大量函数的访问权限。我是否正确地说,没有办法创建可以在上下文之外调用的自定义访问器,而无需将它们全部实例化/绑定到完整的可能原型函数集?

1 个答案:

答案 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;
}