Javascript reference vs binding…what's the difference?

前端 未结 3 1199
暗喜
暗喜 2020-12-16 01:17

I recently read the following in Kyle Simpson\'s You Don\'t Know JS: ES6

\"[ES6 modules export] actual bindings (almost like pointers) to the identifiers in your inn

3条回答
  •  北海茫月
    2020-12-16 01:43

    Despite @Bergi's great answer I'd like to give a more detailed response for users with less background knowledge.

    Name Bindings

    A name binding is the association of an identifier with a named memory chunk (variable) according to the lexical scope rules of Javascript. Name bindings are required because an identifier can exist in different scopes and thus be used for different variables:

    function f() { let x = 0 }
    
    let x = 1;
       
    { let x = 2 }
        
    { let x = 3;
      { let x = 4; 
        { console.log(x) } // logs 4
      }
    }

    Once the name binding process is done, console.log(x) refers to x of the surrounding scope, which is bound to the value 4.

    A name binding decides which variable an identifier refers to in a particular scope.

    Primitive and Reference Types

    The associated value of a binding can either represent

    • a value/primitive type
    • or a reference type

    Primitive types are immutable in Javascript. When you pass a primitive to a function or assign it to another identifier, you actually operate with copies of values. The identity of a primitive value is given by its value, i.e. it has no identity.

    Reference types are mutable in Javascript. When you pass a reference type to a function or assign it to another identifier, you actually operate with a copy of its reference, which is a value as well. Thus you pass a-reference, not by-reference - this distinction is crucial: Javascript has only call-by-value evaluation strategy, not call-by-reference. Reference types have an identity that is separated from their values. Hence they can be shared across name bindings.

    const x = "no identity",
     y = "no identity";
    
    const o = {foo: "identity"},
     p = {foo: "identity"};
     
    // value types don't have identity
    console.log(x === y); // true
    
    // reference types have identity
    console.log(o === p); // false
    
    let q = o;
    
    // mutations of reference types can be shared
    q.bar = "mutation";
    console.log(o); // {foo: "identity", bar: "mutation"}
    
    // but rebindings can't be chared
    q = {baz: "rebinding"};
    console.log(q); // {baz: "rebinding"}
    console.log(o); // {foo: "identity", bar: "mutation"}

    A reference creates identity and the ability to share a corresponding value.

    ES6 Module Bindings

    An ES6 module exports a new type of name binding, which was previously unknown in JavaScript. When you import an exported binding of a module A, you create a binding of an import name and a reference. However, this reference doesn't refer to an object but to the export binding of A. Now we can share not only reference types but also primitives across modules.

提交回复
热议问题