我希望能做的是这样的事情:
var where = new Where();
where('a'); // returns a string 'WHERE a' that I can chain against
where('a').andWhere('b'); // reuturns 'WHERE a AND b' that is also chainable
where('a').andWhere('b').orWhere('c'); // 'WHERE a AND b OR c', and so on ...
where方法应返回所有意图和目的的字符串,包含所有类似字符串的方法,但使用两种自定义andWhere
和orWhere
方法。
当我尝试从Sting.prototype继承时,我的where方法返回了一个对象,而不是一个字符串。当然,如果我直接从方法返回一个字符串,它们没有andWhere
和orWhere
方法,所以链接破坏了。
下面的代码实现了我想要的,但它通过污染String.prototype来实现。有没有办法获得相同的行为,但是封装在自定义对象中?
Object.defineProperty(String.prototype, "andWhere", {
value: function _andWhere(clause) {
return [this, 'AND', clause].join(' ');
},
configurable: true,
enumerable: false,
writeable: true
});
Object.defineProperty(String.prototype, "orWhere", {
value: function _orWhere(clause) {
return [this, 'OR', clause].join(' ');
},
configurable: true,
enumerable: false,
writeable: true
});
function where(clause){
return ['WHERE', clause].join(' ');
}
where('a').andWhere('b').orWhere('c');
// => 'WHERE a AND b OR c'
修改
我仍然希望直接访问该对象的所有字符串方法。换句话说,返回的对象就像一个字符串,但有几个方法。例如:
var whereStr = where('a').andWhere('b').orWhere('c');
whereStr.length; // => 18
whereStr.concat(' and so on'); // => 'WHERE a AND b OR c and so on'
如果它有任何区别,这主要是针对Node,但理想情况下适用于任何最近的(ES5)javascript实现。再次,如果我很糟糕并且使用String.prototype,这可以完美地运行,我希望有一种方法可以替换掉。
答案 0 :(得分:4)
更新在将“长度”属性创建为“getter”的示例中添加。
function Where(conditional) {
var thisObj = this;
//Setup the length property's "getter"
this.__defineGetter__( "length", function() {
return thisObj.clause.length;
});
this.start( conditional );
}
Where.prototype = {
AND_STR: " AND ",
OR_STR: " OR ",
add: function(conditional, prefix) {
this.clause += prefix + conditional;
},
and: function(conditional) {
this.add( conditional, this.AND_STR );
return this;
},
or: function(conditional) {
this.add( conditional, this.OR_STR );
return this;
},
start: function(conditional) {
this.clause = "WHERE " + conditional;
},
toString: function() {
return this.clause;
}
}
//Use it like this (this shows the length of the where statement):
alert( new Where( "a" ).and( "b" ).or( "c" ).length );