闭合样式有什么区别

时间:2020-03-05 18:38:41  来源:igfitidea点击:

javascript中有两种流行的闭包样式。我首先将其称为匿名构造函数:

new function() { 
  var code...
}

以及内联执行函数:

(function() {
  var code...
})();

两者之间在行为上有区别吗?一个比另一个更好吗?

解决方案

回答

第二个示例将在创建函数后执行该函数。

编辑:这不是真的。

回答

@Lance:第一个也在执行。与命名构造函数进行比较:

function Blah() {
    alert('blah');
}
new Bla();

这实际上也是在执行代码。匿名构造函数也是如此...

但这不是问题;-)

回答

两种情况都将执行该函数,唯一真正的区别是表达式的返回值可能是什么,以及" 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

回答

好吧,我做了这样的页面:

<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>

在上面的代码中,输出类似于:

Hello Inside Function

  Hello Outside Function

  World Inside Function

...然后,我们会收到错误消息,因为未在函数外部定义" b"!

因此,我相信第二种方法更好……更安全!

回答

它们都通过执行代码块来创建闭包。就样式而言,出于两个原因,我更喜欢第二种:

乍看之下,代码实际上将被执行并不是立即显而易见的。该行看起来像是在创建一个新函数,而不是将其作为构造函数执行,但这并不是实际发生的情况。避免执行与实际情况不符的代码!

同样,((function(){...})();`也是很好的书挡标记,因此我们可以立即看到我们正在进入和离开闭包范围。这很好,因为它会提醒程序员阅读它的范围更改,并且在进行文件的某些后处理(例如缩小)时特别有用。