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

Binding Object Prototype Functions to Object in Javascript

背景

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

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 待命。

"CHANGE THE PROTOTYPE_OBJECT PARAMS":应用程序的编写方式不是一个选项。

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

您似乎排除了所有可能的解决方案。如果你想要一个解决方案,你将不得不适应使用其中一个选项。如果你在很多地方传递访问器函数,并且你希望它们永久绑定到你的对象(这样你就不必也传递对象),那么你将不得不改变你做事的方式。

最干净的方法是在构造函数中定义方法,并让这些方法使用构造函数局部变量作为对象引用,并依赖于构造函数闭包而不是使用 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;
}