Why 'this' is referring to Window object in below code snippet?


Why 'this' is referring to Window object in below code snippet?



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);





Because splitName(name); has no calling context
– CertainPerformance
Jul 2 at 3:39


splitName(name);





Also because it is run in non-strict mode, otherwise it would be undefined.
– ASDFGerte
Jul 2 at 3:44


undefined





Javascripts .call() and .apply() methods allow you to set the context for a function.
– Aravind S
Jul 2 at 3:46





Possible duplicate of JavaScript this refers to window instead of object inside function
– melpomene
Jul 2 at 3:46





Also, stackoverflow.com/questions/3127429/….
– melpomene
Jul 2 at 3:46




5 Answers
5



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


Function#call()




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);



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.


splitName


this


emp


this


window




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);



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);



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).


console.log(this)



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



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);






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages