最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

scope - Alternative to 'self = this' with object in javascript - Stack Overflow

programmeradmin3浏览0评论

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.

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.

Share Improve this question asked Sep 6, 2012 at 13:51 SamuelSamuel 12.3k6 gold badges51 silver badges72 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 9

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

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/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 mon 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;
}

You appear to be confusing two things.

a) Regular functions

function CreatePerson(name) {
    // create a new object
    var person = {};
    // or (if you want to provide a prototype)
    var person = Object.create(...);

    // fill it with some more data
    person.name = name;
    person.foo = 123;
    person.bar = function() { /* ... your method body ... */ }; 
}

That's invoked like:

var person = CreatePerson("Jack");

b) Constructors

function Person(name) {
    // called after a Person is created,
    // `this` is bound to the new object
    // and its prototype is set to `Person.prototype`

    this.name = name;
    this.foo = 123;
    this.bar = function() { /* ... your method body ... */ }; 
}

var person = new Person("Jack");

Note the special new syntax here.

When using this style, you'll probably want to create the methods only once, not for every created instance:

function Person(name) {
    // called after a Person is created,
    // `this` is bound to the new object
    // and its prototype is set to `Person.prototype`

    this.name = name;
    this.foo = 123;
}
Person.prototype.bar = function() {
    /* ... your method body ... */
};

var person = new Person("Jack");

Doing like this works.

If you only want to access the this within the function you can do like this. you use the return {hello:hello} to declare the function and you don't need do to it, unless it's what you want

example 1

       function _persons(array) {
          this.available = array;
          this.write = function () {
              writedata(this.available, '#array2');
          };
          this.SortAge = function () {
              array.sort(pare);
              writedata(this.available, '#array3');
          };
          array.sort(pareName);
      } 
     var users = new _persons(myarray);

example 2

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

      var a = "john";
      var newPerson = new Person(a); 
      newPerson.hello(); var
      otherPerson = new Person("annie"); 
      otherPerson.hello();
发布评论

评论列表(0)

  1. 暂无评论