javascript chainable嵌套子类

时间:2015-03-03 22:42:00

标签: javascript prototype prototypal-inheritance

我有效地尝试构建包含子对象或其他功能的可链接对象。

它应该像这样使用:

val().rules.phone("someValue");

到目前为止:

var val = function(){
  var validator = function(){
    this.fields = [];
    return this;
  }
  validator.prototype = {
    addField: function(fieldName){
       this.fields.push(fieldName);
       return this;
    },
    rules: {
      phone: function(){
        //RETURNING THIS DOES NOT RETURN THE PARENT SCOPE
        //IT RETURNS SCOPE OF PHONE FUNCTION
        return this;
      }
    }
  }
  return new validator();

}

我还尝试通过原型链接进行循环引用:

var val = function(){
    var validator = function(){
        this.fields = [];

        return this;
    }

    var rules = function(){
        validator.call(this);
    }
    rules.prototype = Object.create(validator.prototype);
    rules.prototype.constructor = rules;
    rules.prototype.phone = function(){
    console.log('hone');   
    }

    validator.prototype = {
        addField: function(fieldName){
            this.fields.push(fieldName);    
            return this;
        },
        rules: new rules()

    }

   return new validator();
}

var z = val().rules;
//no 'addFields' function exists on the validator object in the chain.
console.log(z);

问题:

在第一个val().rules.phone()中返回其函数的范围而不是父范围。它应该返回验证器范围。

在第二个示例中,val().rules DOES在其原型链上具有验证者作为父级,但是addFields打印未定义,并且在跟踪链时在控制台中不存在。

我知道我通过添加规则文字来解决问题。我可以用直接放在原型对象上的函数实现链接。这是我自己的澄清。有没有其他可能的方法来实现相同的样式用法?

2 个答案:

答案 0 :(得分:1)

var val = function(){
    var validator = function(){
        this.fields = [];

        return this;
    }

    var rules = function(){
        if(!this instanceof rules) return new rules();
        validator.call(this);
        return this;
    }
    validator.prototype = {
        addField: function(fieldName){
            this.fields.push(fieldName);    
            return this;
        },
        rules: rules

    }
    rules.prototype = Object.create(validator.prototype);
    rules.prototype.phone = function(){
    console.log('hone');   
    }



   return new validator();
}

z = val().rules实际上会返回一个对象而不是函数。这就是为什么你无法使用prototype

答案 1 :(得分:1)

您可以通过此方式获得所需的API:

var validator = function(){
    this.fields = [];
    this.rules = new rules(this);
}
validator.prototype = {
    addField: function(fieldName){
        this.fields.push(fieldName);    
        return this;
    }
};

var rules = function(validator) {
  this.validator = validator;
}
rules.prototype = {
  addField: function(fieldName) {
    this.validator.addField(fieldName);
    return this;
  },
  phone: function() {
    console.log("phone");
  }
};

v = new validator();
v.rules.addField("hello");
v.rules.phone();

使rules继承validator在语义上和实际上都存在问题。你的validator.prototype

validator.prototype = {
    addField: function(fieldName){
        this.fields.push(fieldName);    
        return this;
    },
    rules: new rules()
}

将在所有rules个对象之间共享相同的validator对象,这可能不是您想要的。但是如果你修复了这个问题,通过在rules构造函数中创建一个validator对象,你会有一个无限循环,因为validator构造函数会调用rules构造函数,并且rules构造函数会调用validator构造函数(因为rules validator)。