是否可以向String
实例添加方法,例如
x = "123"
x.method = function() { console.log("test") }
x.method()
答案 0 :(得分:3)
是的,你可以做到。您必须首先获取字符串原语并使其成为字符串 instance ,但是:
x = new String("123");
x.method = function() { console.log("test") };
x.method();
JavaScript既有字符串原语,也有字符串实例。在您的原始代码中,当您写下:
x.method = ...;
...从变量x
检索字符串原语并将其提升为您添加方法的字符串实例,但由于字符串 instance 从未存储回x
变量,当您尝试调用它时,该方法不存在。 (是的,这个 反直觉。)
通过在上面使用new String(...)
,我实际上得到了字符串实例并将其存储在x
中。然后,因为它是一个合适的对象,我可以添加属性。
您还可以向String.prototype
添加方法,如下所示:
String.prototype.capitalize = function() {
return this.substring(0, 1).toUpperCase() + this.substring(1);
};
console.log("testing".capitalize()); // "Testing"
有些人认为这是不好的做法。其他人说这正是为什么我们有原型继承,所以我们可以使用原型来增强东西。虽然我从来没有看到人们提升String.prototype
时遇到任何问题,但当人们加强Array.prototype
时(因为人们坚持misuing for-in
)和{{ 1}}。
答案 1 :(得分:3)
字符串和数字是自动编排的原语,这意味着当您对它们执行OO操作时,它们将被转换为“字符串”和“数字”类,但随后会立即取消装箱。
您的代码评估为:
x = "123"
(new String(x)).method = function() { console.log("test") }
(new String(x)).method() // Error
您的第二次调用失败,因为您正在处理完全不同的String对象。作为T.J.声明,你可以通过使x
成为一个String对象来解决这个问题,但这不是常见或推荐的做法。
您可以通过将方法添加到String.prototype
来扩展所有字符串:
x = "123"
String.prototype.method = function() { console.log("test") }
x.method()
此调用的计算方式与(new String(x)).method()
相同,但由于该方法存在于原型中,因此将调用它。
答案 2 :(得分:1)
您可以使用ECMA5
定义新属性Object.defineProperty(String.prototype, "test", {
value: function test() { console.log('test:',this) },
configurable: true,
enumerable: false,
writeable: true
});