最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Is a variable declaration the same as a variable's binding? - Stack Overflow

programmeradmin1浏览0评论

MDN documentation states:

let bindings are created at the top of the (block) scope containing the declaration, monly referred to as "hoisting". Unlike variables declared with var, which will start with the value undefined, let variables are not initialized until their definition is evaluated. Accessing the variable before the initialization results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?

Previously I thought the variable keyword and variable name together prised a declaration, but in a question I asked recently, the answerer said they are actually an initialization.

MDN documentation states:

let bindings are created at the top of the (block) scope containing the declaration, monly referred to as "hoisting". Unlike variables declared with var, which will start with the value undefined, let variables are not initialized until their definition is evaluated. Accessing the variable before the initialization results in a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?

Previously I thought the variable keyword and variable name together prised a declaration, but in a question I asked recently, the answerer said they are actually an initialization.

Share Improve this question asked Jun 17, 2018 at 16:55 nCardotnCardot 6,6158 gold badges56 silver badges100 bronze badges 4
  • 1 Variable binding is when the piler assigns a variable to a specific scope (where that variable will be available), declaration is assignment of value to that variable. – Pavan Bahuguni Commented Jun 17, 2018 at 16:59
  • 1 Here is a useful excerpt in the spec. The text block along with below productions are imho useful in this context. Note that afaik technically, there is a difference between declarations and definitions, which however does not exist in javascript, as declarations are always definitions (unlike e.g. c++). – ASDFGerte Commented Jun 17, 2018 at 18:03
  • As contrast, here is the same section for var, note that the "Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created.", in contrast to let, where "A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer's AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created.". This is very likely the reason for the temporal deadzone, no reading uninitialized RAM! – ASDFGerte Commented Jun 17, 2018 at 18:10
  • To conclude things, imho the "hoisted part" (the creation of the variable) is the declaration/definition (introduces the name and allocates/reserves memory), while the non-hoisted part (even named "LexicalBinding" for let), is the "binding", or initialization of the variable. – ASDFGerte Commented Jun 17, 2018 at 18:33
Add a ment  | 

3 Answers 3

Reset to default 6

I'm sorry for using two different terms when writing that MDN paragraph. For all purposes in that article, "variable" and "binding" should be understood as the same thing. But let's go into details.

A variable declaration creates the variable (as an abstract entity). It tells the piler that it should introduce a new variable, and also can tell it about a name, a type to be held, an initial value, a scope etc. (depending on the language). In JS, there are different kinds of declarations that do different things, for example

  • var has a name, an optional initialiser and scoping rules specific to var
  • function has a (sometimes optional) name, the value is always given and known to be a function
  • const has a name, a required initialiser, should be immutable, and has lexical scoping

A binding is the association of a variable name with the variable entity, for example "x refers to the variable declared with class x". Such bindings depend on the scope, i.e. in every different scope there are different bindings and so the identifier x might refer to different things in different scopes.
Given the scoping rules of JavaScript, a variable declaration also causes bindings for itself to be created in the respective scopes.

So the binding is what makes the name available to be used. That's what I referred to as "the let binding is created at the top of the scope". It has nothing to do with the variable existing, having memory allocated for it, or being initialised.

A declaration just says that something exists. In JavaScript you can declare variables, functions and (more recently) classes.

In some languages (e.g. C, C++) it's possible to declare something without defining it. For example:

// this declares a function exists with a given signature, but doesn't define its implementation
void someFunction();

someFunction(); // here we call the function, since we know it exists

// here we define the function, which we have to do at some point
void someFunction() { /* ... */ }

This pattern is less mon in modern languages, where the declaration and the definition tends to be bined, but it's useful to understand the distinction seeing as your question seems largely about terminology.

Variables can be declared, however they don't have definitions.

let b; // we declare that there's a variable 'b'

Instead you can assign a variable:

b = 5; // assignment
let c = 6; // declaration and assignment in one statement

The concept of binding in puter science has many forms. For example, when you type foo in your code, binding is the act of working out which variable/function/type/... should be used. In JavaScript this is pretty straightforward, but in some languages it can get pretty hairy (due to things like overload resolution and so forth).

However I don't believe that's what MDN means when they talk about let bindings. I believe it's a shorthand for "let declaration and assignment", as we saw above.

Regardless, I wouldn't worry too much about that term. The most important bit to understand from the paragraph you've quoted is that let and const are tighter versions of var, introduced in recent versions of the language to address pitfalls and surprises that came from the way var works.

Previously I thought the variable keyword and variable name together prised a declaration

You're right.

var a;
var b = 1;
let c;
let c = 2;
const d = 3;

These are all declarations of variables (even though const technical variables can't vary, or more precisely, they cannot be reassigned).

It's just that var is a bit sloppy and surprising.

You could declare a var more than once within the same scope:

var a = 1;
var a = 2;

This won't work with let:

let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared

Scoping on var can be surprising too:

for (var i = 0; i < 10; i++)
{
    var inner = 1;
}

console.log(inner); // prints 1 even though you might think this would be an error

Or worse:

for (var i = 0; i < 10; i++)
{
    for (var i = 0; i < 10; i++)
    {
        console.log('hello');
    }
}

At a glance you might think this would print hello 100 times (10*10), but actually it is only printed 10 times because both loops use the same variable. This is a type of programmer error that the language should really prevent. If that code used let i instead, it would produce a syntax error.

As for hoisting you can think of it as though all the var declarations were moved to the top of the containing function.

function foo()
{
    doThing();
    var i = 0;
    doSomethingElse();
    for (var j = 0; j < 10; j++)
    {
        var k = 10;
    }
}

Even though that's how you might write the code, it behaves as though you had written:

function foo()
{
    var i; // all declarations hoisted to top of containing function scope
    var j;
    var k;

    doThing();
    i = 0;
    doSomethingElse();
    for (j = 0; j < 10; j++)
    {
        k = 10;
    }
}

This is why you can write:

i = 10;
var i;

The var is moved up in the code, so it behaves as:

var i;
i = 10;

You can think of let as not being moved. Therefore it is an error to reference it before it is declared.

The main thing to understand here is that the js engine actually visits a let statement inntwo different situations (as well as every other statement, but it particularily matters here). It is visited once during parsing, when it generates an AST and also analyzes the scopes and the variables. It also creates a list of variables for each scope. Now when the code gets executed, the engine visits the statement a second time (or more often if its inside a loop / function / whatever) and now finally initializes the variable and assigns a value to it. So "hoisting" is basically just caused because of the parsing / executing stages, the engine knows that a variable exists before it reaches the declaration statement during execution as it has already parsed it before.

Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?

The keyword actually causes an entry in the scope record, which will then get turned into a storage space during execution. On the other hand the statement itself causes an initialization during execution. So its actually hard to say when a declaration happens, thats a question of words. Its mon to say

That variable was declared at line 10

Its declared in that block

so wether "declaration" refers to the statement or the scope assignment is up to you :)

the answerer said they are actually an initialization.

Actually the answerer prefered to call it "initialization" and not "declaration" to not confuse readers, but well in reality its confusing as human languages are not as clearly defined as machine ones.

发布评论

评论列表(0)

  1. 暂无评论