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

本文翻译自:What do parentheses surrounding an object/function/class declaration mean? [duplicate]

This question already has answers here : 这个问题已经在这里有了答案
Closed 5 years ago . 5年前关闭。

I'm new to both JavaScript and YUI . 我是JavaScript和YUI的新手。 In YUI library examples, you can find many uses of this construct: 在YUI库示例中,您可以找到此构造的许多用法:

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

I think the last couple of parentheses are to execute the function just after the declaration. 我认为最后一对括号是要在声明之后执行函数。

... But what about the previous set of parentheses surrounding the function declaration? ...但是围绕函数声明的上一组括号呢?

I think it is a matter of scope; 我认为这是范围问题; that's to hide inside variables to outside functions and possibly global objects. 那就是将内部变量隐藏到外部函数以及可能的全局对象中。 Is it? 是吗? More generally, what are the mechanics of those parentheses? 一般来说,这些括号的作用机理是什么?


#1楼

参考:https://stackoom.com/question/1QEH/围绕对象-函数-类声明的括号是什么意思-重复


#2楼

Juts to follow up on what Andy Hume and others have said: 紧跟安迪·休姆(Andy Hume)和其他人所说的话:

The '()' surrounding the anonymous function is the 'grouping operator' as defined in section 11.1.6 of the ECMA spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf . 匿名函数周围的'()'是ECMA规范第11.1.6节中定义的'分组运算符': http : //www.ecma-international.org/publications/files/ECMA-ST/Ecma-262 .pdf

Taken verbatim from the docs: 从文档中逐字获取:

11.1.6 The Grouping Operator 11.1.6分组运算符

The production PrimaryExpression : ( Expression ) is evaluated as follows: 产生的PrimaryExpression :( Expression )评估如下:

  1. Return the result of evaluating Expression . 返回Expression的计算结果。 This may be of type Reference. 这可能是参考类型。

In this context the function is treated as an expression. 在这种情况下,该功能被视为表达式。


#3楼

See this question . 看到这个问题 The first set of parenthesis aren't necessary if you use a function name, but a nameless function requires this construct and the parenthesis serve for coders to realize that they've viewing a self-invoking function when browsing the code (see one blogger's best-practices recommendation ). 如果您使用函数名称,则不需要第一套括号,但是无名函数需要这种构造,并且括号可以使编码人员认识到他们在浏览代码时正在查看自调用函数(请参阅博客的最佳内容)。 -实践建议 )。


#4楼

The first parentheses are for, if you will, order of operations. 第一个括号用于表示操作顺序。 The 'result' of the set of parentheses surrounding the function definition is the function itself which, indeed, the second set of parentheses executes. 函数定义周围的括号集合的“结果”是函数本身,实际上,第二个括号集合执行该函数。

As to why it's useful, I'm not enough of a JavaScript wizard to have any idea. 至于为什么有用,我对JavaScript向导还不够了解。 :P :P


#5楼

It is a self-executing anonymous function. 它是一个自执行的匿名函数。 The first set of parentheses contain the expressions to be executed, and the second set of parentheses executes those expressions. 第一组括号包含要执行的表达式,第二组括号执行这些表达式。

It is a useful construct when trying to hide variables from the parent namespace. 当尝试从父名称空间隐藏变量时,这是一个有用的构造。 All the code within the function is contained in the private scope of the function, meaning it can't be accessed at all from outside the function, making it truly private. 函数内的所有代码都包含在函数的私有范围内,这意味着根本无法从函数外部对其进行访问,从而使其成为真正的私有。

See: 看到:

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

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


#6楼

Andy Hume pretty much gave the answer, I just want to add a few more details. 安迪·休ume(Andy Hume)几乎给出了答案,我只想补充一些细节。

With this construct you are creating an anonymous function with its own evaluation environment or closure, and then you immediately evaluate it. 使用此构造,您将使用其自己的评估环境或闭包创建一个匿名函数,然后立即对其进行评估。 The nice thing about this is that you can access the variables declared before the anonymous function, and you can use local variables inside this function without accidentally overwriting an existing variable. 这样做的好处是,您可以访问在匿名函数之前声明的变量,并且可以在此函数内使用局部变量,而不会意外覆盖现有变量。

The use of the var keyword is very important, because in JavaScript every variable is global by default, but with the keyword you create a new, lexically scoped variable, that is, it is visible by the code between the two braces . var关键字的使用非常重要,因为在JavaScript中,每个变量默认情况下都是全局变量,但是使用关键字您可以创建一个新的, 词法范围的变量,即, 两个大括号之间的代码都可以看到该变量。 In your example, you are essentially creating short aliases to the objects in the YUI library, but it has more powerful uses. 在您的示例中,您实际上是在为YUI库中的对象创建简短的别名,但是它具有更强大的用途。

I don't want to leave you without a code example, so I'll put here a simple example to illustrate a closure: 我不想让您没有代码示例,因此在这里我将举一个简单的示例来说明闭包:

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

What is going on here? 这里发生了什么? In the function add_gen you are creating an another function which will simply add the number n to its argument. 在函数add_gen中,您将创建另一个函数,该函数将简单地将数字n添加到其参数中。 The trick is that in the variables defined in the function parameter list act as lexically scoped variables, like the ones defined with var . 诀窍在于,在函数参数列表中定义的变量中充当像词法作用域一样的变量,就像用var定义的变量一样。

The returned function is defined between the braces of the add_gen function so it will have access to the value of n even after add_gen function has finished executing, that is why you will get 5 when executing the last line of the example. 返回的函数在add_gen函数的大括号之间定义,因此即使add_gen函数完成执行后,它也可以访问n的值,这就是为什么在执行示例的最后一行时将获得5的原因。

With the help of function parameters being lexically scoped, you can work around the "problems" arising from using loop variables in anonymous functions. 通过对函数参数进行词法范围划分,您可以解决由于在匿名函数中使用循环变量而引起的“问题”。 Take a simple example: 举一个简单的例子:

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

The "expected" result could be the numbers from zero to four, but you get four instances of fives instead. “预期”结果可能是从零到四的数字,但是您却得到了四个实例,即五。 This happens because the anonymous function in setTimeout and the for loop are using the very same i variable, so by the time the functions get evaluated, i will be 5. 发生这种情况是因为setTimeout和for循环中的匿名函数使用的是相同的 i变量,因此,当函数被求值时, i将为5。

You can get the naively expected result by using the technique in your question and the fact, that function parameters are lexically scoped. 通过使用问题中的技术以及事实,即函数参数在词法范围内,您可以获得天真的预期结果。 (I've used this approach in an other answer ) (我在其他答案中使用了这种方法)

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

With the immediate evaluation of the outer function you are creating a completely independent variable named j in each iteration, and the current value of i will be copied in to this variable, so you will get the result what was naively expected from the first try. 通过立即评估外部函数,您将在每次迭代中创建一个名为j的完全独立的变量,并且i的当前值将被复制到该变量中,因此您将获得第一次尝试时幼稚的结果。

I suggest you to try to understand the excellent tutorial at http://ejohn.org/apps/learn/ to understand closures better, that is where I learnt very-very much. 我建议您尝试在http://ejohn.org/apps/learn/上阅读出色的教程,以更好地理解闭包,这是我学到的很多东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值