假设一个库具有以下功能:
class Stuff {
total () {
return 4; // might be some calculation
}
}
但是您想更新它以使用吸气剂,例如:
class Stuff {
get total () {
return 4;
}
}
是否有一种以向后兼容的方式进行此类更改的方法?那么使用该库的代码假定函数不会中断?
stuff.total // should work with new version
stuff.total() // hopefully this still works
编辑:这个问题更多地是关于库的演变(更一般)。另一个是从呼叫站点的角度来考虑一种特定的解决方案。
答案 0 :(得分:5)
您不应该这样做。 stuff.total
应该是数字或函数,但不能两者都选。这将使将来的代码非常混乱且难以维护。
也就是说,您可以按照自己的意愿做一些事情:
class Stuff {
get total () {
const callable = function ( ) {
return 4;
};
callable[Symbol.toPrimitive] = callable;
return callable;
}
}
const stuff = new Stuff;
console.log( stuff.total );
console.log( stuff.total( ) );
console.log( 1 + stuff.total );
console.log( 1 + stuff.total( ) );
// stuff.total is a function, not a number!
console.log( typeof stuff.total );
console.log( stuff.total.toString( ) );
// But if it's implicitly coerced to a string, it's toString is not called:
console.log( '' + stuff.total);
console.log( `${stuff.total}` );
尽管有一些警告。 stuff.total
是一个吸气剂,它返回一个函数,而不是一个数字。在期望使用原语的任何地方使用该函数都会导致该函数被调用并使用其返回值,但是它实际上仍然是一个函数。当您登录stuff.total.toString( )
或typeof stuff.total
时,这一点很明显。
答案 1 :(得分:2)
答案大多是“否”,部分是“取决于”。
这取决于现有代码将如何使用结果。在某些情况下,您可以通过返回一个函数来使吸气剂工作,而在其他情况下则不能。
您的代码示例显示了一个返回简单基元数字的函数,这使事情变得更加困难。如果以某种方式使用吸气剂的结果会自动调用其.valueOf()
方法,那么如果返回一个带有.valueOf()
被覆盖的函数,则可以得到所需的行为。
class Doer {
get total () {
var f = function() { return f.valueOf() };
f.valueOf = function() { return 4 };
return f
}
}
const d = new Doer();
const x = 10 + d.total();
const y = 10 + d.total; // The addition forces the .valueOf() evaluation
console.log(x, y);
但是d.total
最终仍是一个函数,而不是数字4
。
如果您要返回一个对象,则可以通过返回继承自Function.prototype
的对象来更轻松地伪造该对象,但仍然很大程度上取决于实际用法。