简体   繁体   English

令人困惑的EcmaScript规范-声明绑定实例化

[英]Confusing EcmaScript Specification - Declaration Binding Instantiation


When I read specification for learn "hoisting" in there FunctionDeclaration happens on step 5 but VariableDeclaration happened step 8 and I think this mean function declaration are given higher priority than variable declaration . 当我在其中阅读有关学习“提升”的规范时,在第5步发生了FunctionDeclaration ,但在第8 发生了VariableDeclaration,并且我认为此均值函数声明的优先级高于变量声明
What do you think why Function Declaration declare fist and is this have any reason? 您认为函数声明为什么要声明拳头,这有什么原因?
Note: You can read this part from this link http://www.ecma-international.org/ecma-262/5.1/#sec-10.5 注意:您可以从此链接http://www.ecma-international.org/ecma-262/5.1/#sec-10.5阅读此部分

I have hypothesis for my question. 我的问题有一个假设。 This is not answer this is hypothesis because I don't really know this question answer apparently people also don't know answer. 这不是答案,这是假设,因为我并不真正知道这个问题,显然人们也不知道答案。
My hypothesis this 我的假设是
Function can override another function but variable can't I think because that first functionDeclaration happens. 函数可以覆盖另一个函数,但我不能认为变量,因为发生了第一个functionDeclaration。

There are two choices, either this code is invalid (eg, syntax error): 有两种选择,或者此代码无效(例如,语法错误):

 function foo() { console.log("foo1"); } var foo = function() { console.log("foo2"); }; foo(); 

...or there is an order to things. ...或者事物有秩序。 In the JavaScript spec, in this case, there's an order to things: 在JavaScript规范中,在这种情况下,事情是有秩序的:

  1. The function declaration creates a binding in the scope for foo which logs foo1 . 函数声明在foo的作用域中创建一个绑定,该绑定记录foo1
  2. The var in var foo = ... has no effect because varAlreadyDeclared is true. varvar foo = ...有没有影响,因为varAlreadyDeclared是真实的。
  3. foo is overwritten with the value resulting from the function expression foo = function() { /*...*/ }; foo被函数表达式foo = function() { /*...*/ };所产生的值覆盖foo = function() { /*...*/ };

Why? 为什么? Because that's how it's specified. 因为那是指定的方式。 More specifically, because a function declaration and a var statement both create a mutable binding in the execution context, so whichever one gets there first creates the binding. 更具体地说,由于函数声明和var语句都在执行上下文中创建了可变绑定 ,因此无论谁先到达那里都将创建绑定。 "First" again needs definition, and so the definition chosen was that the declaration creates the binding first. “第一”再次需要定义,因此选择的定义是声明首先创建绑定。 But both create mutable bindings, and remember that the var foo part and the foo = ... part are handled completely separately. 但是两者都创建可变的绑定,并记住var foo部分和foo = ...部分是完全分开处理的。 Since function declarations are processed before the step-by-step execution of the code, the following does exactly the same thing as the above: 由于函数声明是在逐步执行代码之前进行的,因此以下操作与上述操作完全相同:

 var foo = function() { console.log("foo2"); }; function foo() { console.log("foo1"); } foo(); 

Although the function declaration creates the binding first and sets it to the function that does console.log("foo1") , the foo = ... part happens afterward and updates the binding so that it refers to the new function that does console.log("foo2") . 尽管函数声明首先创建绑定并将其设置为执行console.log("foo1")的函数,但是foo = ...部分随后发生并更新绑定,以便它引用执行console.log("foo2")的新函数console.log("foo2")

Other choices were available to Brendan Eich, but this was the choice he made during those fateful 10 days in May, 1995. :-) And it does follow logically from these decisions: 其他的选择是提供给布兰登·艾克,但是这是他在五月那些致命的10天内的选择,1995年:-)而且从这些决策逻辑如下:

  1. Function declarations create mutable bindings 函数声明创建可变绑定
  2. Function declarations and var declarations create the same kind of bindings 函数声明和var声明创建相同类型的绑定
  3. Function declarations are hoisted (eg, the function is created and assigned to the binding before step-by-step execution begins) 悬挂函数声明(例如,在逐步执行开始之前创建函数并将其分配给绑定)
  4. The declaration part of a var is hoisted, using the initialization value undefined , but the initializer part of var x = y is not set until the step-by-step execution of the code. 使用初始化值undefined提升var声明部分,但是直到逐步执行代码之前,才设置var x = y初始化部分。

Both function declarations and variable declarations are hoisted . 函数声明和变量声明都被吊起

Functions are hoisted first, and then variables. 首先悬挂函数,然后悬挂变量。

foo(); // 1

var foo;

function foo() {
  console.log(1);
}

foo = function() {
  console.log(2);
};

Notice that var foo was the duplicate (and thus ignored) declaration, even though it came before the function declaration. 注意, var foo是重复的声明(因此被忽略了),即使它在函数声明之前。

Also, an interesting fact that subsequent function declarations do override previous ones. 同样,一个有趣的事实是,后续函数的声明确实会覆盖先前的函数。

foo(); // 3

function foo() {
  console.log(1);
}

var foo = function() {
  console.log(2);
};

function foo() {
  console.log(3);
}

More information you can find in the You Don't Know JS: Scope & Closures book 您可以在《 您不知道JS:范围和闭包》一书中找到更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM