将原型函数绑定到此的简洁方法

时间:2013-11-19 20:38:31

标签: javascript refactoring prototype

我使用以下范式来声明类:

var myNamespace = myNamespace || {};
(function () {
    myNamespace.MyClass = function () {
        if (!(this instanceof myNamespace.MyClass)) {
            return new myNamespace.MyClass();
        }

        this.field = 17;

        this.foo = this.foo.bind(this);
        this.bar = this.bar.bind(this);
    };

    myNamespace.MyClass.prototype.foo = function(){
        console.log(this.field + 1);
    };

    myNamespace.MyClass.prototype.bar = function(){
        console.log(this.field + 2);
    };
})();

我使用prototype来避免在每个实例化中重新声明对象方法,并使代码更清晰 - 将类字段与其逻辑分开。
我在每个方法上调用bind,以避免在this指向方法内部错误的方式时出现令人讨厌的错误。

它有效,但它容易出错 - 我必须记得在每个方法上调用bind,并且它太冗长了,特别是当有两种以上的方法时。

是否有更简洁的*方式来声明这些类型的函数(绑定到其类型的this,并在prototype上声明)?

*我知道“干净”没有明确定义 - 一个简单的指标就是代码长度。

3 个答案:

答案 0 :(得分:4)

你不应该像这样绑定你的方法 - 你在每个实例上创建新函数,当你真的应该在原型上有方法来节省内存。如果您创建了100个实例,那么您将创建200个新功能!像这样的简单模式更常见,并且可以正常工作:

var myNamespace = myNamespace || {};
myNamespace.MyClass = (function() {
  function MyClass() {
    this.field = 17;
  }

  MyClass.prototype = {
    constructor: MyClass,
    foo: function() {
      console.log(this.field + 1);
    },
    bar: function(){
      console.log(this.field + 2);
    }
  };

  return MyClass;
}());

答案 1 :(得分:1)

在声明您的课程后附加到您的命名空间:

var myNamespace = myNamespace || {};
(function () {
    var MyClass = function () {
        this.field = 17;
    };

    MyClass.prototype.foo = function(){
        console.log(this.field + 1);
    };

    MyClass.prototype.bar = function(){
        console.log(this.field + 2);
    };
    this.MyClass = MyClass;

}).call(myNamespace);

通过使用命名空间作为范围调用IIFE,可以通过在this对象上公开类来保持模块清洁。

答案 2 :(得分:0)

您可以在单个赋值中压缩一些原型定义,并将命名空间传递给函数调用。

var myNamespace = myNamespace || {};
(function () {
    function MyClass() { 
        this.field = 17;
    };

    MyClass.prototype = {
        foo: function () {
            console.log(this.field + 1);
        },

        bar: function () {
            console.log(this.field + 2);
        }
    };
})(myNamespace);