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

Binding Object Prototype Functions to Object in Javascript

本文关键字:对象 函数 绑定 原型 Javascript      更新时间:2024-02-11

背景

我有一个原型对象,它有几十个函数,可以访问如下列表中的信息:

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

问题

这些访问器fxn被传递到应用程序的不同区域,并在被分配给新对象后被调用。因此,原型函数中的"this"被重新分配(正如javascript中所预期的那样),并导致未定义的类型。

"SO BIND IT":我们可以绑定到函数来设置将创建新函数的"this"。我负担不起在几十个地方为几十种对象类型的100实例化60个新函数。

"CALL IT":调用要求我将原始访问器作为"this"传递,但正如我所说,access_foo.green是在应用程序中的其他地方传递的,不能在调用时引用回access_foo。

"更改PROTOTYPE_OBJECT段落":不是应用程序编写方式的选项。

最后,我需要一个知道其类型并共享对大量函数列表的访问权限的对象。我说的对吗?如果不让它们全部实例化/绑定到一整套可能的原型函数,就无法创建可以断章取义调用的自定义访问器?

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

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