在他的“好的部分”中,克罗克福德建议永远不要使用“新的”。要遵循该规则,您将如何重构以下代码?
function Range(from, to) {
this.from = from;
this.to = to;
}
Range.prototype = {
includes: function(x) {
return this.from <= x && x <= this.to;
},
foreach: function(f) {
for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
toString: function() {
return "(" + this.from + "..." + this.to + ")";
}
};
// Here are example uses of a range object
var r = new Range(1,3); // Create a range object
r.includes(2); // => true: 2 is in the range
r.foreach(console.log); // Prints 1 2 3
我发现了他的additional advice,但目前尚不清楚如何将其应用于此(可能非常常见)的情况。他会建议创建一个包含巨大对象字面值的工厂函数吗?如果是,那效率不高吗? ISTM,在每次调用时,这样的工厂函数会创建重复的函数。换句话说,没有一个原型持有共享自定义方法。
在他的建议中似乎没有说清楚,我希望有人可以清理它。
答案 0 :(得分:2)
我在这里展示如何在不使用new
Range = function(from, to) {
function includes(x) {
return this.from <= x && x <= this.to;
}
function foreach(f) {
for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
}
function toString(){
return "(" + this.from + "..." + this.to + ")";
}
return {
from: from,
to: to,
includes: includes,
foreach: foreach,
toString: toString
};
};
var r = Range(1, 3);
console.log(r.includes(2)); // => true: 2 is in the range
r.foreach(console.log); // Prints 1 2 3
这只是一个例子,但我会遵循@nnnnn所说的 - “只在适当的时候使用它。就我而言,你问题中的代码完全可以正常使用new
并且不会不需要重构。“
编辑:
下面给出的代码将避免创建重复的函数实例
Range = function(from, to) {
return {
from: from,
to: to,
includes: Range.includes,
foreach: Range.foreach,
toString: Range.toString
};
};
Range.includes = function(x) {
return this.from <= x && x <= this.to;
}
Range.foreach = function (f) {
for (var x = Math.ceil(this.from); x <= this.to; x++) f(x);
}
Range.toString = function() {
return "(" + this.from + "..." + this.to + ")";
}
答案 1 :(得分:1)
我认为他会建议这样做:
function Range(from, to) {
if (!(this instanceof Range)) {
return new Range(from, to); // Yes, the new operator is used here, but...
}
this.from = from;
this.to = to;
}
// ... now, the rest of the world can create ranges WITHOUT the new operator:
var my_range = Range(0, 1);
答案 2 :(得分:0)
我喜欢这种技术,我将其称为保证实例:
var Range = function fn(from, to) {
if (!(this instanceof fn)) {
return new fn(from, to);
};
this.from = from;
this.to = to;
}
Range.prototype = {
includes: function(x) {
return this.from <= x && x <= this.to;
},
foreach: function(f) {
for(var x = Math.ceil(this.from); x <= this.to; x++) f(x);
},
toString: function() {
return "(" + this.from + "..." + this.to + ")";
}
};
// Here are example uses of a range object
var r = new Range(1,3); // Create a range object
r.includes(2); // => true: 2 is in the range
r.foreach(console.log); // Prints 1 2 3