javascript 中有两种流行的闭包样式。我首先调用匿名构造函数:
new function() {
var code...
}
和内联执行函数:
(function() {
var code...
})();
这两者之间的行为是否存在差异?一个比另一个“更好”吗?
javascript 中有两种流行的闭包样式。我首先调用匿名构造函数:
new function() {
var code...
}
和内联执行函数:
(function() {
var code...
})();
这两者之间的行为是否存在差异?一个比另一个“更好”吗?
两种情况都会执行函数,唯一真正的区别是表达式的返回值可能是什么,以及函数内部的“this”的值是什么。
基本上的行为
new expression
等效于
var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
result = tempObject;
当然 tempObject 和 result 是你永远看不到的瞬态值(它们是解释器中的实现细节),并且没有 JS 机制来执行“不是对象”检查。
从广义上讲,“new function() { .. }”方法会比较慢,因为需要为构造函数创建 this 对象。
也就是说,这应该不是真正的区别,因为对象分配并不慢,并且您不应该在热代码中使用此类代码(由于创建函数对象和相关闭包的成本)。
编辑:我意识到我错过的一件事是tempObject
将获得expression
原型,例如。(之前expression.call
)tempObject.__proto__ = expression.prototype
@Lance:第一个也在执行。将其与命名构造函数进行比较:
function Blah() {
alert('blah');
}
new Bla();
这实际上也在执行代码。匿名构造函数也是如此......
但这不是问题;-)
他们都通过执行代码块来创建一个闭包。就风格而言,我更喜欢第二种,原因如下:
乍一看,代码实际上会被执行并不是很明显。该行看起来像是在创建一个新函数,而不是作为构造函数执行它,但这并不是实际发生的事情。避免不做看起来像它正在做的事情的代码!
还有(function(){
...})();
制作漂亮的书挡标记,以便您可以立即看到您正在进入和离开闭包范围。这很好,因为它提醒阅读它的程序员注意范围的变化,并且如果您正在对文件进行一些后处理,例如缩小,则特别有用。
好吧,我做了一个这样的页面:
<html>
<body>
<script type="text/javascript">
var a = new function() {
alert("method 1");
return "test";
};
var b = (function() {
alert("method 2");
return "test";
})();
alert(a); //a is a function
alert(b); //b is a string containing "test"
</script>
</body>
</html>
令人惊讶的是(无论如何对我来说)它提醒了“方法1”和方法2“。我没想到会提醒“方法1”。区别在于a和b的值是什么。a是函数本身,而 b 是函数返回的字符串。
是的,两者之间存在差异。
两者都是匿名函数并以完全相同的方式执行。但是,两者之间的区别在于,在第二种情况下,变量的范围仅限于匿名函数本身。不可能意外地将变量添加到全局范围。
这意味着通过使用第二种方法,您不会弄乱全局变量范围,这很好,因为这些全局变量值可能会干扰您可能在其他库中使用或在第三方库中使用的其他一些全局变量.
例子:
<html>
<body>
<script type="text/javascript">
new function() {
a = "Hello";
alert(a + " Inside Function");
};
alert(a + " Outside Function");
(function() {
var b = "World";
alert(b + " Inside Function");
})();
alert(b + " Outside Function");
</script>
</body>
</html>
在上面的代码中,输出类似于:
你好内部函数
你好外部函数
世界内部函数
...然后,您会收到一个错误,因为 'b' 未在函数外部定义!
因此,我相信第二种方法更好……更安全!