如何在JavaScript中编写扩展方法?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (9)

我需要在JS中编写几个扩展方法。我知道如何在C#中做到这一点。例:

public static string SayHi(this Object name)
{
    return "Hi " + name + "!";
}

然后调用:

string firstName = "Bob";
string hi = firstName.SayHi();

我将如何在JavaScript中做这样的事情?

提问于
用户回答回答于

在这种特定情况下,你可以String.prototype像这样分配你的方法:

String.prototype.SayHi = function SayHi() {
    return "Hi " + this + "!";
};

或更好作为一个非枚举属性使用Object.defineProperty(ES5和更高版本,基本上,除IE8和更早版本之外的所有内容):

Object.defineProperty(String.prototype, "SayHi", {
    value: function SayHi() {
        return "Hi " + this + "!";
    }
});

JavaScript是一种典型的语言。这意味着每个对象都由一个原型对象支持。在JavaScript中,该原型由对象的构造函数或新的(ish)ECMAScript5 Object.create函数分配。

在前一种情况下(构造函数),分配给对象的原型由prototype构造函数的属性定义。所以如果你有一个叫做的构造函数Foo

function Foo() {
}

...然后声明

var f = new Foo();

...分配Foo.prototypef实例作为其原型对象。从而:

function Foo(b) {
    this.baz = b;
}
Foo.prototype.bar = function bar() {
    console.log(this.baz);
};

var f = new Foo("Charlie");
f.bar(); // logs "Charlie"

所以在你的例子中,因为firstName是一个String实例(实际上是一个字符串原语,但不用担心,它会String在需要时自动提升为实例),它的原型是String.prototype,因此添加一个属性String.prototype,引用你的SayHi函数使得该函数可用所有String实例。

正如DougR在评论中指出的那样,与C#扩展方法的一个区别是C#的扩展方法可以在null引用上被调用(如果你有一个string扩展方法,string s = null; s.YourExtensionMethod();实际上可行)。这不适用于JavaScript; null是它自己的类型,没有原型可以扩展它。

有关这些示例中函数名称的简要说明,例如

Object.defineProperty(String.prototype, "SayHi", {
    value: function SayHi() {
// HERE ------------^
        return "Hi " + this + "!";
    }
});

Foo.prototype.bar = function bar() {
// AND HERE -----------------^
    console.log(this.baz);
};

在这种形式下,我们使用一个带有名称的函数表达式(一个“命名函数表达式”,又名NFE),因为有问题而出名(在IE8和更早的版本上;以及真正的旧版本的一对的其他浏览器)。随着其他一切都死了,IE8 几乎已经死了,没有必要再担心NFE了。(即使在IE8中,上述内容也是可以的。)

扫码关注云+社区