Home > Enterprise >  JavaScript object related question that what will be the output of below code?
JavaScript object related question that what will be the output of below code?

Time:02-11

var x = 3;
var one = {
  x:2,
  two: {
    x:1,
    three:function(){
        return this.x;
      
    }
  }
}

var go = one.two.three;

 console.log(one.two.three()   ""   go());
 

Anyone can explain to me why output coming 13 why not 1-undefined?

CodePudding user response:

this keyword has a different binding that can change during runtime, depending on how the function was invoked.

When a function is on an object, and is accessed through that object, it's this context will be that object (unless explicitly bound otherwise, but I'll add notes on that later). This means this.x is referencing the same variable as one.two.x

When you reference that same function into a global variable, the this context becomes the global space (e.g. the window object on browsers, or globalThis in NodeJS). When this happens, this.x is now referencing global variable x.

There are other situations where this context rules are different, such as function closures or class functions.

Functions also have .bind method that returns a new function with an explicitly bound this variable.

e.g:

var x = 3;
var one = {
  x:2,
  two: {
    x:1,
    three:function(){
        return this.x;
      
    }
  }
}

one.two.three = one.two.three.bind(one);

var go = one.two.three;

console.log(one.two.three()   ""   go()); // prints 22

There are also arrow functions, which implicitly have the this context bound to it's lexical scope... e.g:

var x = 3;
var one = {
  x:2,
  two: {
    x:1,
    three: () => {
        return this.x;

    }
  }
}


var go = one.two.three;

console.log(one.two.three()   ""   go()); // prints 33

This above example prints 33, because the lexical scope is the global scope, thus this.x is referencing global variable x.

Hope this answers your question without creating more questions.

Further Reading:

CodePudding user response:

Interesting. I think it has something to do with scopes.

console.log(one.two.three()   ""   go());
//equals console.log(1   ""   3);

will output 13 (String) because:

  • one.two.three() returns 1
  • go() returns 3
  • those numbers are concatenated into String with "" (empty string) in between (instead of - as you may have asked)

Why go() returns 3

var x = 3;

// var go = one.two.three;
// equals 
var go = function() {
  return this.x
}

The declaration var go = one.two.three; assigns one.two's three method as a function into the variable go in the global scope. The same scope with go, one, and x (with the value 3), that was declared before declaring one and go (var x= 3;).

Based on your whole codes, this.x's this is in the global scope. and this.x is 3. So running go() returns 3.

one.two.three is a global function → notice there's no (), so assigning a function to global scope's variable go will make the function's scope global. → go function is run under global's scope


Why one.two.three() returns 1

Well, one.two.three is a method inside the object two, which is inside the object one. While the definition looks the same,

function() {
  return this.x;
}

when you run three method of two object, return this.x's this refers to the method's parent object (which is two, three's parent object is two). So, this.x refers to two.x which is 1.

Hence, in this case return this.x; outputs 1.

one.two.three() is 1 → notice the () which means run the functionthree method is run under two's scope


Addition

This will output 1-undefined because:

  • y is not defined in the global/one/go scope
  • I use - as a delimiter in console.log
var one = {
  y:2,
  two: {
    y: 1,
    three:function(){
        return this.y;
      
    }
  }
}

var go = one.two.three;

console.log(one.two.three()   "-"   go());

CodePudding user response:

To assign an object method to a variable, it needs to be bandaged using the bind() function, and if the global variable window is passed to the context, the answer will be 13

*var go = one.two.three.bind(window);*

if the object is one the answer will be 12

*var go = one.two.three.bind(one);*

if the object is two the answer will be 11

*var go = one.two.three.bind(two);*
  • Related