0

Can someone help me understand why the below code prints Inside splitName function = [object Window]
Why 'this' is referring to Window object?

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(window.fName);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320

5 Answers5

0

Can use Function#call() to pass the object context in

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName.call(this, name);
  }
}

emp.setName('ABC DEF');
console.log(emp.fName);
charlietfl
  • 170,828
  • 13
  • 121
  • 150
0

I'd recommend changing your method splitName to be a method on your object. This way it will know that this will refer to your object emp. Otherwise because it's a standalone function it would mean this is referring to window by default since there is no calling context.

let emp = {
  fName: '',
  lName: '',
  splitName: function(n) {
    console.log("Inside splitName function = " + this)
    let nameArr = n.split(' ');
    this.fName = nameArr[0];
    this.lName = nameArr[1];
  },
  setName: function(name) {
    console.log("Inside setName function = " + this)
    this.splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(window.fName);
console.log(emp.fName);
Spencer Wieczorek
  • 21,229
  • 7
  • 44
  • 54
0

Update your splitName function declaration as Arrow function then it will take this as it's parent's scope and it will work as expected.

You can learn about how "this" works here.
And learn about Arrow functions here.

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = (n) => {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName(name);
  }
}

emp.setName('ABC DEF');
console.log(emp.fName + ' ' + emp.lName );
console.log(window.fName);
Karan
  • 12,059
  • 3
  • 24
  • 40
0

Because of context and lexical scoping Lexical Scope and execution context in javascript. In javascript every function (non arrow) have execution context where as ES6 arrow functions doen't have their own execution context.

for constructor functions when we initiate them using new, javascript engine creates execution context for it and you assigns this to it. but for non constructor functions if they are not invoked using function.Call or function.Apply i.e this is not set then due to lexical scoping they get window scope being most outer scope.

try console.log(this) in browser console, this will print Window (as that is parent object or most outer scope in DOM).

also have a look at this. How does the "this" keyword work?

Rajnikant
  • 2,176
  • 24
  • 23
0

You can use apply function to bind this of the inner function to the enclosing object. This happens because in a closure of this type this refers to window scope (global scope).

let emp = {
  fName: '',
  lName: '',
  setName: function(name) {
    console.log("Inside setName function = " + this)
    let splitName = function(n) {
      console.log("Inside splitName function = " + this)
      let nameArr = n.split(' ');
      this.fName = nameArr[0];
      this.lName = nameArr[1];
    }
    splitName.apply(emp,[name]);
  }
}
emp.setName('ABC DEF');
console.log(window.fName);
Abhisar Tripathi
  • 1,569
  • 10
  • 21