2012-02-19 66 views
52

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

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

我会怎么做在JavaScript这样的事情:

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

,然后叫什么名字?

回答

94

在这种特定的情况下,你的方法分配给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" 
在你的榜样

那么,既然firstNameString实例(实际上是一个原始的字符串,不过不用担心,它就会自动地晋升为String实例在必要时),它的原型是String.prototype,所以将属性添加到String.prototype,该属性引用您的SayHi函数可使该函数在所有String实例上可用。

由于DougR在评论中指出,从C#扩展方法的一个区别是,C#的扩展方法can be called on null references(如果你有一个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是死了,有没有必要担心NFEs了。(即使在IE8中,上面也没关系。)

+0

@DougR:对不起,标准注释清理。当评论变得过时时,mod或高级用户可以将其删除(mod可以直接执行,高级用户必须在审查队列中合作)。我已经更新了答案,表明你已经标记了这一点。 :-) – 2015-01-11 10:24:14

+1

@Grundy:谢谢,是的,'String s = null'的全部点''部分是使用's.YourExtensionMethod()'!欣赏这一点。 :-) – 2015-01-11 11:07:02

+0

感谢您高亮显示扩展方法对空实体有效。 – Rama 2016-04-19 07:40:16