Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to 'self = this' with object in javascript

I have this code:

function Person(name){      
    var self = this;

    this.name = name;

    function hello(){
        alert("hello " + self.name);
    }

    return {
        hello: hello
    };
}

var newPerson = new Person("john");

newPerson.hello();

I want to be able to use the 'this' keyword to access the 'name' property in the 'hello' function; I want an alternative to using the 'self' variable.

Except using the $.proxy function of jquery to control the context, how can I write the same code but without the variable 'self'?

I want a code that looks like below but 'name' is always 'undefined' when I call 'newPerson.hello()'. I don't know why because I have always believed that the scope of a function is always the object at the left of the dot of the caller and in this case, it's 'newPerson' that have been assign a value 'john' when creating the object.

function Person(name){              
    this.name = name;

    function hello(){
        alert("hello " + this.name);
    }

    return {
        hello: hello
    };
}

var newPerson = new Person("john");

newPerson.hello();

Thank you.

like image 589
Samuel Avatar asked Nov 28 '25 06:11

Samuel


2 Answers

You can use .bind to force the owner of a function to be whatever object you pass. So, you can write your Person object like so:

function Person(name){ 
    this.name = name;

    var hello = function(){
        alert("hello " + this.name);
    }.bind(this);

    return {
        hello: hello
    };
}

This will ensure that .hello always executes in the context of the Person that is calling it.

Here's a demo:

--- jsFiddle DEMO ---

like image 114
jackwanders Avatar answered Nov 30 '25 19:11

jackwanders


Don't use return by default when using the new keyword the function will return this you will need to change how your function is declared how ever.

Here is a fiddle

http://jsfiddle.net/SaintGerbil/9SAhD/

function Person(name){              
    this.name = name;
    this.hello = function (){
        alert("hello " + this.name);
    }
}

var newPerson = new Person("john");

newPerson.hello();​

EDIT if you require name to be private then here is an alternative

function Person(name){              
    var _name = name;
    this.hello = function (){
        alert("hello " + _name);
    }
}

var newPerson = new Person("john");

newPerson.hello();​

In answer to your question there are 4 ways to call a function These affect the value of this they are

  • Constructor call (using the new keyword) where this is the new object which is returned automatically.
  • Method call if a function is attached to an object and called from it then this is the object called from.
  • Function call a direct call to a function will result in this being the global object, (a common mistake when calling a contstructor without new)
  • Apply\Call call when using a method to specify what this should be (see jackwanders as an example)

FURTHER EDIT

So taking your desired code at the start and explaining what is happening.

function Person(name){
    this.name = name; // 1

    function hello(){ // 2
        alert("hello " + this.name); // 3
    } 

    return {
        hello: hello
    }; //4
}

Person as a function can be called two ways:

var x = Person("ted");

and

var x = new Person("jimmy");

Since you have named Person with a capital it implies that you are expecting people to use new.
So sticking with that we enter the function and javascript creates a new object and assigns it to this.

  • line 1 we then attach a 'name' variable to this and initialise with the passed parameter.
  • line 2 we then attach a 'hello' function to this.
  • line 3 the function expects to have a 'name' variable exist attached to this (which it does for now).
  • line 4 rather than return this (default behavior) we are now declaring a new object and attaching the function to it. This new object does not have a 'name' variable with in its scope.

So when you create the object you get an object with a function attached but it cannot get to the variable it needs to execute correctly. Which is why you are getting the undefined.

Does that make sense I always worry that I'm waffling when I have to expand the textbox?

Or if I wrote out your function as verbosely as possible it would look something like this.

function Person(name){
  var this = new Object();
  this.name = name;
  var hello = function (){
    alert("hello " + this.name);
  } 
  this.hello = hello;

  var that = new Object();
  that.hello = hello;

  return that;
}
like image 39
Mark Broadhurst Avatar answered Nov 30 '25 21:11

Mark Broadhurst



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!