3

I have following code block in javascript:

const obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"

    function a() {
      console.log(this.name)
    }
    a();

  }
}

obj.func1();

why am I not getting any console.log state about the this keyword? I am really confused, its neither obj nor undefined nor window object

ADyson
  • 57,178
  • 14
  • 51
  • 63
sriram hegde
  • 2,301
  • 5
  • 29
  • 43
  • Do something like ```a.bind(this)();``` – Sajeeb Ahamed Apr 21 '20 at 12:51
  • _"Ignore HTML part"_ ... if the HTML is not relevant then please do not include it in your example! I will edit the question for you, this time. Please see also https://stackoverflow.com/help/minimal-reproducible-example – ADyson Apr 21 '20 at 12:52
  • I know bind exist but why am I not getting any output not even errors! – sriram hegde Apr 21 '20 at 12:53
  • Ok sorry for adding html part – sriram hegde Apr 21 '20 at 12:53
  • Ok I edited it into a runnable snippet. It does seem to produce output, albeit not the value you expected, I would assume. You maybe need to read up on the scope of `this` in functions, especially nested functions (or "closures" as they're sometimes known). You could potentially start here: https://stackoverflow.com/questions/346015/javascript-closures-and-this – ADyson Apr 21 '20 at 12:55
  • If you use arrow functions, you'll get a different result. Demo: https://jsfiddle.net/9ju3kbht/ . It wasn't clear which of the two "name" values you were actually expecting it to output? The demo shows how to get each one. – ADyson Apr 21 '20 at 12:58

4 Answers4

2

When you have an object with a method that returns a function the this escapes the object scope and refers to the window, unless you bind it or use arrow functions.

So what your this.name is returning in a normal environment is just an empty string. That's why you don't see anything—like @dellink said. window.name is "" if you don't set it. So what you actually see is just a string with nothing inside.

The reason why it's logging some weird property in your example is because of the Stack Overflow sandbox. Here, the this keyword does not refer to the general window object, but to a different object that does in fact have a name property with some value.

Check it:

console.log(this.name)
Ludolfyn
  • 1,806
  • 14
  • 20
1

tricky thing is that when you define a function a - it's getting defined in a global scope.

var obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"
    console.log(this); // obj (!) *2
    function a() {
      console.log(this); // window (!) *3
    }
    a();

  }
}
obj.func1();
console.log (a()) // window (!) *1

Look at point number 1: a function exists. And it's context is window. And this is what is happening in a first-place - defining functions and variables.

When you call "obj.func1();" it really calls in a context of obj (*2)

When you invoke a function context switch again to a window. (*3)

qiAlex
  • 4,290
  • 2
  • 19
  • 35
1
const obj = {
  name: "sri1",
  func1: function() {  // <-- 1
    const name = "sri2"

    function a() { // <-- 2
      console.log(this.name)
    }
    a();

  }
}

Normally this points to the window object of the browser.
But inside an object, if we define a property with an anonymous function then the this points to the object itself. But another function inside the function? No, it points to the window object.

So, for your example. I've marked your code with two reference points by comments.

  1. Mark 1 function, it's the function of the object's property. So this points to the obj object.
  2. Mark 2 function, it's inside the mark 1 function so now, this inside the function a() points to the window object. (If you don't believe me then check it by using console.log(this) inside the function a())

How can I get the object's this inside the inner function?

There are several ways to achieve this. I am mentioning few of them.

Using arrow function.

An arrow function doesn't alter the reference of this pointer. It points to the blocks this in which block the function lays.

const obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"

    const a = () => { // Using arrow function
      console.log(this.name)
    }

    a();
  }
}

Keep the previous this into a variable.

You can put the this into a variable say, that, then access the value using that.name.

const obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"
    const that = this; // Put this into that

    function a() {
      console.log(that.name); // Access the name using that.name
    }

    a();
  }
}

Bind this when you call the function.

You can bind the this with the function to use inside it.

const obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"

    function a() {
      console.log(this.name)
    }

    const withThis = a.bind(this); // Make a function reference with `this` bindings
    withThis(); // Call the function
  }
}

Using call() or apply()

The call() method calls a function with a given this value and arguments provided >individually.

While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

const obj = {
  name: "sri1",
  func1: function() {
    const name = "sri2"

    function a() {
      console.log(this.name)
    }

    a.call(this); // call() binds the `this`
    // Or
    a.apply(this); // apply() also binds the `this`
  }
}
Sajeeb Ahamed
  • 6,070
  • 2
  • 21
  • 30
0

You log window.name in your function. It is '', if you don't set it.

dellink
  • 544
  • 3
  • 16