0

i have problem about scoping in javascipt. I tried to create new object using the "new" keyword without any problem. The code looks like this

"use strict";

 function Person() {
     this.name = "john doe";
     console.log(this.name);
 }

 Var foo = new Person() 

The problem i encountered is when i try to add inner function the scope of the name variable becomes undefined inside the inner function

 "use strict";

 function Person() {
         this.name = "john doe";

         Function speak() {
                   console.log("my name is" + this.name);
         }

         speak();
  }

  var foo = new Person();

 //error: "cannot read property 'name' of undefined"

Can somebody explained what seems to be the problem? Thank guys

cute_programmer
  • 332
  • 3
  • 13
  • Appears to be a duplicate question: https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var-to-declare-a-variable – RetroCoder Dec 09 '17 at 01:19
  • Also in w3schools: https://www.w3schools.com/js/js_strict.asp – RetroCoder Dec 09 '17 at 01:21
  • Possible duplicate of [What does "use strict" do in JavaScript, and what is the reasoning behind it?](https://stackoverflow.com/questions/1335851/what-does-use-strict-do-in-javascript-and-what-is-the-reasoning-behind-it) – RetroCoder Dec 09 '17 at 01:23
  • I think its not a duplicate my issue is about lexical scopping. I declared this.name one level up higher to my inner function speak. If the lexical scoping is applied the inner function should be able to use the 'this.name' declared inside Person function which is not. – cute_programmer Dec 09 '17 at 02:32
  • 1
    I think i know the problem if im not wrong. This is sumthing to do with "new" keyword. Using "new" keyword created a plain object not a function(which is an object also) – cute_programmer Dec 09 '17 at 03:07

3 Answers3

1

With Strict mode when you are creating the object with new Person(), this refers to the window object which does not have the property called name. property called name belongs to the Person object. Thus you are getting error cannot read property 'name' of undefined.

User another variable to hold the value of Person object's this to use that inside the inner function.

var thatObj = this;

"use strict";

function Person() {
  this.name = "john doe";
  var thatObj = this;
  function speak() {
    console.log("my name is: " + thatObj.name);
  }

  speak();
}

var foo = new Person();
Mamun
  • 66,969
  • 9
  • 47
  • 59
0

You can also give speak the same scope as this. It should be noted that this will also make it a public function, so speak can be called from outside of the Person class.

function Person() {
    this.name = "john doe";

    this.speak = function() {
        console.log("my name is " + this.name);
    };
         
    this.speak();
}

var foo = new Person();
vqdave
  • 2,361
  • 1
  • 18
  • 36
  • Yhup this code works. But adding this to speak wont make it inner function anymote it now becomes a funtion of person object – cute_programmer Dec 09 '17 at 04:12
  • @arnoldemzi Another option is to keep your original code, except change the call from `speak();` to `speak.call(this);` – Paul Dec 09 '17 at 04:15
0

this is determined by how a function is invoked, not where the function is defined. Since this.name is inside its own scope it has lost a reference to this.name instead it is referencing a global window object.

It is important to be aware of the fact when using this keyword inside of nested functions you are more than likely going to lose reference to the object that you are inside of and your this keyword will end up referencing the global object.

There is also another solution to your example using call or apply methods. call and apply will allow you to change the value of this when function is executed.

'use strict';

function Person () {
    this.name = 'john doe';

    function speak () {
        console.log('my name is: ' + this.name);
    }

    speak.call(this);
}

var foo = new Person();
Durdona A.
  • 310
  • 3
  • 15