围绕对象/函数/类声明的括号是什么意思?[重复]

2020/10/05 08:01 · javascript ·  · 0评论

我是JavaScript和YUI的新手在YUI库示例中,您可以找到此构造的许多用法:

(function() {
    var Dom = YAHOO.util.Dom,
    Event = YAHOO.util.Event,
    layout = null,
        ...
})();

我认为最后一对括号是要在声明之后执行函数。

...但是围绕函数声明的上一组括号呢?

我认为这是范围问题;那就是将内部变量隐藏到外部函数以及可能的全局对象中。是吗?一般来说,这些括号的作用机理是什么?

它是一个自执行的匿名函数。第一组括号包含要执行的表达式,第二组括号执行这些表达式。

当尝试从父名称空间隐藏变量时,这是一个有用的构造。函数内的所有代码都包含在函数的私有范围内,这意味着它根本无法从函数外部访问,从而使其真正成为私有的。

看到:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

http://peter.michaux.ca/articles/javascript-namespacing

安迪·休ume(Andy Hume)几乎给出了答案,我只想补充一些细节。

使用此构造,您将使用其自己的评估环境或闭包创建一个匿名函数,然后立即对其进行评估。这样做的好处是,您可以访问在匿名函数之前声明的变量,并且可以在此函数内使用局部变量,而不会意外覆盖现有变量。

var关键字的使用非常重要,因为在JavaScript中,每个变量默认情况下都是全局变量,但是使用关键字您可以创建一个新的,词法范围的变量,即,两个大括号之间的代码都可以看到该变量在您的示例中,您实际上是在为YUI库中的对象创建简短的别名,但是它具有更强大的用途。

我不想让您没有代码示例,因此在这里我将举一个简单的示例来说明闭包:

var add_gen = function(n) {
  return function(x) {
    return n + x;
  };
};
var add2 = add_gen(2);
add2(3); // result is 5

这里发生了什么?在函数add_gen中,您将创建另一个函数,该函数将简单地将数字n添加到其参数中。诀窍在于,在函数参数列表中定义的变量中,它们充当词法范围变量,就像用var定义的变量一样

返回的函数add_gen函数的大括号之间定义,因此即使add_gen函数完成执行后,它也可以访问n的值,这就是为什么在执行示例的最后一行时将获得5的原因。

通过对函数参数进行词法范围划分,您可以解决由于在匿名函数中使用循环变量而引起的“问题”。举一个简单的例子:

for(var i=0; i<5; i++) {
  setTimeout(function(){alert(i)}, 10);
}

“预期”结果可能是从零到四的数字,但您却得到了四个五的实例。发生这种情况是因为setTimeout和for循环中的匿名函数使用的是相同的 i变量,因此,当函数被求值时,i将为5。

通过使用问题中的技术以及事实,即函数参数在词法范围内,您可以获得天真的预期结果。(我在其他答案中使用了这种方法

for(var i=0; i<5; i++) {
  setTimeout(
     (function(j) {
       return function(){alert(j)};
     })(i), 10);
}

通过立即评估外部函数,您将在每次迭代中创建一个名为j的完全独立的变量,并且i的当前值将被复制到该变量中,因此您将获得第一次尝试时幼稚的结果。

我建议您尝试在http://ejohn.org/apps/learn/阅读出色的教程,以更好地理解闭包,这是我学到的很多东西。

...但是上一轮围绕所有函数声明的括号会如何?

具体来说,它使JavaScript将'function(){...}'构造解释为嵌入式匿名函数表达式。如果省略括号:

function() {
    alert('hello');
}();

您会收到语法错误,因为JS解析器会看到'function'关键字,并假设您正在启动以下形式的function语句

function doSomething() {
}

...而且没有函数名称就不能有函数语句。

函数表达式和函数语句是两种不同的构造,它们以非常不同的方式处理。不幸的是,语法几乎是相同的,因此它不仅使程序员感到困惑,甚至解析器也很难分辨出您的意思!

紧跟安迪·休姆(Andy Hume)和其他人所说的话:

围绕匿名函数的'()'是ECMA规范第11.1.6节中定义的'分组运算符':http : //www.ecma-international.org/publications/files/ECMA-ST/Ecma-262 .pdf

从文档中逐字获取:

11.1.6分组运算符

产生的PrimaryExpression:(Expression)评估如下:

  1. 返回评估Expression的结果这可能是参考类型。

在这种情况下,该功能被视为表达式。

关于此问题的一些注意事项:

  • 括号:

    浏览器(引擎/解析器)将关键字函数与

    [optional name]([optional parameters]){...code...}
    

    因此,在像function(){}()这样的表达式中,最后一个括号没有意义。

    现在想想

    name=function(){} ; name() !?
    

是的,第一对括号强制匿名函数转换为变量(存储的表达式),第二对强制执行评估/执行,因此 function(){} )()很有意义。

  • 实用程序:

    1. 为了在加载时执行一些代码并将使用的变量与页面的其余部分隔离,尤其是在名称冲突可能的情况下;

    2. 将eval(“ string”)替换为

      (新函数(“字符串”))()

    3. 为“ = ?: ”操作符包装长代码,例如:

      结果= exp_to_test?(function(){... long_code ...})():(function(){...})();

第一个括号用于表示操作顺序。函数定义周围的括号集合的“结果”是函数本身,实际上,第二个括号集合执行该函数。

至于为什么有用,我对JavaScript向导的了解还不够。:P

看到这个问题如果您使用函数名称,则不需要第一套括号,但是无名函数需要这种构造,并且括号可以使程序员在浏览代码时意识到他们正在查看自调用函数(请参阅博主的最佳文章)。 -实践建议)。

本文地址:http://javascript.askforanswer.com/weiraoduixiang-hanshu-leishengmingdekuohaoshishenmeyisizhongfu.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!