what is the javascript mechanism/rules that allow `p.foo = o.foo` to return a reference to the function `foo`?

I’m currently studying javascript by following the book “you dont know js” series.

In the “this & object prototype” section, when discussing “indirect references to functions”, the author states

  • Running function from attribute string
  • Javascript - local scope objects not accessible from nested function
  • External Javascript calling functions from another external javascript file
  • Adding listener functions to a JavaScript object
  • Call random function Javascript, but not twice the same function
  • Is there a way to get the current function from within the current function?
  • function foo() {
      console.log( this.a );
    }
    
    var a = 2;
    var o = { a: 3, foo: foo };
    var p = { a: 4 };
    
    o.foo(); // 3
    (p.foo = o.foo)(); // 2
    

    The result value of the assignment expression p.foo = o.foo is a
    reference to just the underlying function object. As such, the
    effective call-site is just foo(), not p.foo() or o.foo() as you might
    expect. Per the rules above, the default binding rule applies.

    So apparently, (p.foo = o.foo) return a reference to the function foo. But what is the mechanism/rules that allow (p.foo = o.foo) return a reference to the function foo? In other words, why a simple assignment return a reference to foo function?

  • What does { [native code] } mean in WebKit's Inspector?
  • passing number to function for loop with jquery
  • Javascript function return as object property
  • Difference between Function Binding and Closure in Javascript?
  • Question on Javascript Function Parameters
  • Using event in jQuery custom function
  • 2 Solutions collect form web for “what is the javascript mechanism/rules that allow `p.foo = o.foo` to return a reference to the function `foo`?”

    When I want to understand something like this, I find it helpful to break it down step by step.

    1. o.foo looks at the o object and finds a property named foo. It returns a reference that property, whatever it might be. In this case, the o.foo property is a reference to the function foo.
    2. p.foo = o.foo takes the result from above (a reference to the function foo), creates a property in the p object which is also named foo. So now p.foo is also a reference to the foo function, exactly the same thing as o.foo.
    3. That expression is wrapped in parentheses, so now you have whatever was on the left side of the = sign, or p.foo, which is (as a reminder) still a reference to the foo function.
    4. Now we find the () at the end. This calls whatever function we have on hand at this moment. That is the foo function. Note in particular that we are not calling p.foo(). That would be a method call to the function that p.foo is a reference to, so inside that function, this would be set to p. But we’re not doing that. We’re just calling whatever function was returned by ( p.foo = o.foo ). As before, this is the same foo function, but we’ve now lost any connection it may have ever had to the o object or the p object.
    5. So, when we make that call at the end, we are merely calling the foo function without setting this to any particular object. Because of that, when we make the call, this is set to undefined.
    6. But we’re not running in strict mode, so JavaScript “helpfully” doesn’t want to give us an undefined this, so it sets this to the window object in a browser or the global object in Node.
    7. Previously we did var a = 2;. So the window or global object actually now has a property named a, and the value of that property is 2.
    8. So now when we do the console.log(this.a), we pick up the a property from the window or global object. That value is 2.

    What if all this code was not running at the global level, but instead it was inside a function? What would happen then?

    function test() {
      function foo() {
        console.log( this.a );
      }
      
      var a = 2;
      var o = { a: 3, foo: foo };
      var p = { a: 4 };
    
      o.foo(); // 3
      (p.foo = o.foo)(); // was 2, but now is undefined
    }
    
    test();

    The assignment operator = is an expression in JavaScript that produces (returns) the assigned value. Because it is an expression it can be used anywhere an expression is allowed, such as inside parenthesis.

    For example:

    let test = (a = b = c = { name: 'test' })
    

    The code above would first evaluate the expression in the parenthesis and point the variables c, b, and a to the test object (in that order), then it would point test to the produced value from this expression. After that line is executed, a, b, c, and test will all point to the same object.

    Similarly,

    (p.foo = o.foo)
    

    Would produce o.foo back (technically it would produce whatever o.foo is pointing to, which is the function foo).

    As far as

    (p.foo = o.foo)()
    

    By adding the additional () after the parenths, we are telling the engine that we want to invoke whatever the expression (p.foo = o.foo) ends up producing. Thus we end up invoking the function foo. Similar patterns is used in IIFEs.

    A helpful rewrite would be to think of the line above as doing this:

    let produced = (p.foo = o.foo)
    produced()
    

    Further reading about statements vs expressions.