0

I have a JavaScript object like this:

var ali = {   firstname: 'ali', 
            say_hi: function(firstname) { 
            alert("Greetings " + firstname + ", you are talking to " + this.firstname + "!"); 
   } 
}; 

var some_ref = ali.say_hi; 
some_ref("Sabir");

It alerts:

Greetings Sabir, you are talking to undefined!

But I want this:

Greetings Sabir, you are talking to ali!

I think self.firstname refers to window object so it gives undefined.

Can anyone please help me understand what the problem is in this and how to solve it?

timolawl
  • 4,934
  • 9
  • 28
Sony Khan
  • 1,112
  • 2
  • 17
  • 35

4 Answers4

1

To understand why it is returning undefined instead of ali, you have to understand JavaScript binding.

If you are accessing a method through a reference instead of directly through its owner object, as you are doing, the method loses its implicit binding, and this stops referencing its owner object and goes back to its default binding, meaning the global object (or undefined in strict mode).

Ultimately, what matters is the manner in which the function is invoked.

See below for more information (there are exceptions, but it can be generally summarized as the following):

Breakdown from YDKJS: Determining this

Now, we can summarize the rules for determining this from a function call's call-site, in their order of precedence. Ask these questions in this order, and stop when the first rule applies.

  1. Is the function called with new (new binding)? If so, this is the newly constructed object.

    • var bar = new foo()
  2. Is the function called with call or apply (explicit binding), even hidden inside a bind hard binding? If so, this is the explicitly specified object.

    • var bar = foo.call( obj2 )
  3. Is the function called with a context (implicit binding), otherwise known as an owning or containing object? If so, this is that context object.

    • var bar = obj1.foo()
  4. Otherwise, default the this (default binding). If in strict mode, pick undefined, otherwise pick the global object.

    • var bar = foo()

Note: In ES6, this is the lexical this for fat arrow functions => and with object short hand notation (e.g., sampleMethod() {}), meaning that this takes on the outer context as reference.

timolawl
  • 4,934
  • 9
  • 28
1

what is issue in this and how to solve

The value of this depends on how the function is called. By assigning the function to a variable and calling it as f(), this will refer to the global object (or undefined in strict mode). Since there is no global variable with name firstname, this.firstname will resolve to undefined.

If you want this to refer to a specific object, you can .bind the function:

var some_ref = ali.say_hi.bind(ali);

To learn more about this, have a look at some of the many internet references:

Community
  • 1
  • 1
Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
0

Dont use this just ali.firstname it will work fine

var ali = {
  firstname: 'ali',
  say_hi: function(firstname) {
    alert("Greetings " + firstname + ", you are talking to " + ali.firstname + "!");
  }
};
var some_ref = ali.say_hi;
some_ref("Sabir");
elreeda
  • 4,187
  • 2
  • 16
  • 43
0

I recommend that you use object constructors to avoid repeating the var ali = ... code when you make new people. I am basing the following code on Eloquent JavaScript.

function Person(firstname) {
  this.firstname = firstname;
}

Person.prototype.say_hi = function(greeter_name) {
  alert("Greetings " + greeter_name + ", you are talking to " + this.firstname + "!");
}

var ali = new Person("Ali");

ali.say_hi("Sabir"); 
Tina Vall
  • 172
  • 3
  • 11
  • While this is certainly useful, it doesn't explain the issue the OP has. – Felix Kling Apr 28 '16 at 16:10
  • `this.propertyName` is typically used in constructors, so I rewrote what the OP intends to do with a constructor. – Tina Vall Apr 28 '16 at 16:15
  • But you completely ignored the `var some_ref = ali.say_hi; some_ref("Sabir");` issue, which would still be an issue with your solution. – Felix Kling Apr 28 '16 at 16:17
  • I edited my answer, I merely reshuffled the function assignment to a direct call. They both work. His issue was with the use of `this`. – Tina Vall Apr 28 '16 at 16:23
  • I'm confused now... your update has the exact same issue the OP is complaining about in the question. Again, how does this solve the OP's issue? – Felix Kling Apr 28 '16 at 16:24
  • Sorry, I made a mistake. Only worked when I first posted the answer. I wasn't paying attention. – Tina Vall Apr 28 '16 at 16:27