JavaScript向字符串实例添加方法

4

是否可以向String实例添加方法,例如

x = "123"
x.method = function() { console.log("test") }

x.method()

如果你将 x = "123" 改为 x = new String("123"),是可以的,但这不是一个好的做法。 - Fabrício Matté
如果你想让这个函数在所有字符串中都可用,你也可以将它添加到 String.prototype 中,但正如其他人所说,修改原生对象的原型并不是一个好习惯。String.prototype.method = function () { console.log(this); } - plalx
@lemil77请不要建议w3schools.com。看一下这个:http://en.wikipedia.org/wiki/W3Schools。 - A human being
@FabrícioMatté:在扩展实例方面没有什么“不好的做法”。虽然有一些反对扩展内置原型的争论(尽管我从未见过扩展String.prototype会有任何问题),但不是针对个别实例的。 - T.J. Crowder
嗨@Stillakid,哇,我不知道W3Schools.com上有那么多错误。正如http://w3fools.com/中提到的,其他地方也有一些问题,但我推荐的那个似乎没问题。 - lemil77
显示剩余4条评论
3个回答

4

是的,你可以做到。但是,你需要首先将字符串基本类型转换为字符串实例:

x = new String("123");
x.method = function() { console.log("test") };

x.method();

JavaScript 既有字符串原始值,也有字符串实例。在您的原始代码中,当您写下以下内容时:
x.method = ...;

...从变量x中检索到字符串原始值并提升为字符串实例,然后添加了方法,但由于字符串实例没有存回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(因为人们坚持使用错误使用for-in),以及Object.prototype时出现了问题。

3

字符串和数字是自动装箱的原始类型,这意味着当您对它们执行面向对象操作时,它们会被转换为“String”和“Number”类,但随后立即取消装箱。

您的代码评估结果为:

x = "123"
(new String(x)).method = function() { console.log("test") }

(new String(x)).method() // Error

你的第二个调用失败是因为你正在处理一个完全不同的字符串对象。正如T.J.所说,你可以通过将x变成一个字符串对象来解决这个问题,但这不是一个常见或推荐的做法。

你可以通过在String.prototype中添加方法来扩展所有字符串:

x = "123"
String.prototype.method = function() { console.log("test") }

x.method()

这个调用与(new String(x)).method()的求值方式相同,但由于该方法存在于原型中,因此将调用它。


还有,如何从函数中访问字符串? - e-info128
@e-info128 你可以在方法内部使用 this,它将是封装的 String 而不是基本类型的 string,但大多数操作都是相同的。例如:String.prototype.parseInt = function () { return parseInt(this); } - Brian Nickel
如果你需要原始字符串,你可以在函数内部使用 this.toString() - Brian Nickel

1

您可以使用ECMA5定义新属性

Object.defineProperty(String.prototype, "test", {
value: function test() { console.log('test:',this) },
  configurable: true,
  enumerable: false,
  writeable: true
});

查看完整答案: 不修改原型扩展核心类型


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接