为了理解发生了什么,人们必须非常仔细地看看实际做了什么。
Function.prototype.method = function(name, f) {
this.prototype[name] = f;
return this;
}
这部分很清楚,它是扩展任何对象的Prototype的“捷径”。
魔法发生在代码的第二部分,之前定义的函数提供了一个自我执行的函数作为第二个参数!
String.method('de', function() {
var entity = {
lt : '<',
gt : '>'
};
return function() {
return this.replace(/&([^&;]+);/g, function(a, b) {
// "this" will refer to the object the function is bound to.
document.write("<br> a=" + a + " b=" + b);
var r = entity[b];
return typeof r === 'string' ? r : a;
});
};
}()); <-- The magic happens here!
这意味着,JavaScript解释器将使用的“第一内部”函数的返回值(一个直接提供给String.method
)作为实际功能,由于“第一内”功能分配给它之前执行到String.prototype
。
下面的代码是一样的,但在本地范围内增加了一个变量(de
)。上面的方法不污染范围,这是一个更好的方法来实现这一点。你甚至可以打开它进一步将entity
放在本地范围内。
var de = function() {
var entity = {
lt : '<',
gt : '>'
};
return function() {
return this.replace(/&([^&;]+);/g, function(a, b) {
// "this" will refer to the object the function is bound to.
document.write("<br> a=" + a + " b=" + b);
var r = entity[b];
return typeof r === 'string' ? r : a;
});
};
};
String.method('de', de());
现在,你的问题就如何a
和b
开始发挥作用! 这与String.replace
在传递的第二个参数是一个函数时的行为有关。注释中提供的link DCoder解释了这非常好!参数a
是整个匹配的子字符串,b
是第一个匹配的“加括号的子匹配”。
[String.replace'的文档](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter)应该可以回答这个问题。 – DCoder
这些是lt和gt? – Darek
容易理解,如果你快速发现自执行函数会发生什么,否则它会花费你几分钟的时间想知道为什么'String.de'不会打印返回函数的代码。 – clentfort