4

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

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

x.method()
4

3 回答 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.

于 2013-03-29T22:07:24.507 回答
3

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

您的代码评估为:

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

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

Your second call is failing because you are dealing with an entirely different String object. As T.J. stated, you can get around this by making x a String object, but this is not a common or recommended practice.

You can extend all strings by adding the method to String.prototype:

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

x.method()

This call evaluates the same way as (new String(x)).method() but since that method exists in the prototype, it will get called.

于 2013-03-29T22:10:51.883 回答
1

You could define new properties using ECMA5

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

See the complete answer: Extending core types without modifying prototype

于 2013-03-29T22:38:35.440 回答