简体   繁体   中英

Trying to understand `this` in javascript

I have an object with a number of functions:

var someScopeScopedObject = {
  myFunction1: function () {
    console.log('foo');
  },

  myFunction2: function () {
    this.myFunction1();
  }

 init: function (callback) {
    callback();
  }
}

So if I call someScopeScopedObject.myFunction2 that works fine

But If I do someScopeScopedObject.init(someScopeScopedObject.myFunction2) then I get an error that this.myFunction1 is undefined

Why is this not valid when I call into the function that way?

The keyword this refer's to the functions scope. Not the global scope. You declare a function called myFunction2 , the this refers to the scope of this function and not the scope in which this function is declared.

It isn't like in languages, like C#, where this refers to the current instance of the class, whether you are in one another method.

this refers to the function in which it is declared, So in your example,

var someScopeScopedObject = {
  myFunction1: function () {
    console.log('foo');
  },

  myFunction2: function () {
    this.myFunction1();
  }

 init: function (callback) {
    callback();
  }
}

myFunction1 is not declared inside myFunction2, so

` myFunction2: function () {
        this.myFunction1();
      }.

is not possible, because this.myFunction1(); tries to call method myfunction1 which should be declared inside myfunction1 which is not declared there.

Edit:

  1. someScopeScopedObject.myFunction2(); is possible because you are calling the method myFunction1 which is defined inside someScopeScopedObject

  2. someScopeScopedObject.init(someScopeScopedObject.myFunction2); is not possible because, you pass someScopeScopedObject.myFunction2 as a callback function in this case here to the init function,

init: function (callback) { callback(); }

It then calls

myFunction2: function () { this.myFunction1(); }

here you refer this.myFunction1(); --- This doen not exist, since you are refering to myfunction1 defined inside myfunction2, which is not!

When you pass myFunction2 as an argument to something, it loses the reference to the object it belongs to. this now refers to the function itself, and not someScopeScopedObject , hence your problem :)

This is also why some libraries take an object context for methods, ie. jasmine's spyOn(someScopeScopedObject, "myFunction2") , to keep the scoping correct.

An example work-around (like the one used by jasmine) could look like this:

var someScopeScopedObject = {
  myFunction1: function () {
    console.log('foo');
  },

  myFunction2: function () {
    this.myFunction1();
  },

  init: function (context, callbackName) {
    context[callbackName]();
  }
}

This would allow you to do the following:

someScopeScopedObject.init(someScopeScopedObject, "myFunction2");

This is not the prettiest. Alternatively, you can bind the object to the function (so the scope stays the same). This assumes your original code in someScopeScopedObject :

someScopeScopedObject.init(someScopeScopedObject.myFunction2.bind(someScopeScopedObject));

Neither of these are pretty, and, really, that's because it is weird to externally feed a function belonging to an object as a callback to that object.

The best solution might be:

someScopeScopedObject.init(function() {
    someScopeScopedObject.myFunction2();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM