Conceptual overview this
When a function is created, a keyword this is created (in the background), which is linked to an object, and the function operates in this object. In other words, the keyword this can be used in a function, a reference to an object, and the function is the property or method of that object.
Let's look at this object:
<!DOCTYPE html><html lang="en"><body><script> var code = { living:true, age:23, gender:'male', getGender:function(){return cody.gender;} }; console.log(cody.getGender()); // logs 'male' </script></body></html>Note that in the function getGender, since inside the cody object, we can obtain the gender attribute (that is, cody.gender) through . You can also use this to get the cody object, because this points to the cody object.
<!DOCTYPE html><html lang="en"><body><script> var code = { living:true, age:23, gender:'male', getGender:function(){return this.gender;} }; console.log(cody.getGender()); // logs 'male' </script></body></html>In this.gender, this points to a cody object, and the getGender function can operate on a cody object.
The topic about this may be a bit confusing, but it doesn't have to be. Just remember that usually, the object this points to is the object that contains the function, not the function itself (of course there are exceptions, such as using the keywords new or call() and apply()).
Important Tips
- The keyword this is like other variables, the only difference is that you can't change it.
- Unlike other parameters and variables passed to a function, this is a keyword (not a property) in the object that calls the function.
How to determine the value of this?
This is passed to all functions, and its value depends on when the function is called when it is run. Please note here, because this is a very special place you need to remember.
In the following code, the myObject object has a property saysFoo, which points to the function saysFoo. When the sayFoo function is called in the global domain, this points to the window object. When myObject calls a function, this points to myObject.
Because myObject has a property called foo, it is used here.
<!DOCTYPE html><html lang="en"><body><script> var foo = 'foo'; var myObject = {foo: 'I am myObject.foo'}; var sayFoo = function() { console.log(this['foo']); }; // give myObject a sayFoo property and have it point to sayFoo function myObject.sayFoo = sayFoo; myObject.sayFoo(); // logs 'I am myObject.foo' 12 sayFoo(); // logs 'foo' </script></body></html>It is clear that the value of this depends on when the function is called. myObject.sayFoo and sayFoo both point to the same function, but the context of the sayFoo() call is different, so the value of this is different. Below is a similar code, the head object (window) is used explicitly, hoping it will be useful to you.
<!DOCTYPE html><html lang="en"><body><script> window.foo = 'foo'; window.myObject = {foo: 'I am myObject.foo'}; window.sayFoo = function() { ! console.log(this.foo); }; window.myObject.sayFoo = window.sayFoo; window.myObject.sayFoo(); window.sayFoo(); </script></body></html>Make sure that when you have multiple references pointing to the same function, you know clearly that the value of this changes depending on the context of the calling function.
Important Tips
- All variables and parameters except this belong to the static variable scope.
This points to the head object within the embedded function
You may be wondering what happens when using this in a function embedded in another function. Unfortunately in ECMA 3, this does not follow the rules, it does not point to the object where the function belongs, but to the head object (the browser's window object).
In the following code, this in func2 and func3 no longer points to myObject, but rather the head object.
<!DOCTYPE html><html lang="en"><body><script> var myObject = { func1:function() { console.log(this); //logs myObject varfunc2=function() { console.log(this); //logs window, and will do so from this point on varfunc3=function() { console.log(this); //logs window, as it's the head object }(); }(); } }; myObject.func1(); </script></body></html>However, in ECMAScript 5, this issue will be corrected. Now you should be aware of this problem, especially when you pass the value of one function to another.
Look at the code below, pass an anonymous function to foo.func1. When an anonymous function is called in foo.func1 (the function is nested in another function), this will point to the head object in the anonymous function.
<!DOCTYPE html><html lang="en"><body><script> var foo = { func1:function(bar){ bar(); //logs window, not foo console.log(this);//the this keyword here will be a reference to foo object } }; foo.func1(function(){console.log(this)}); </script></body></html>Now you won't forget that if the function containing this is in another function, or is called by another function, the value of this will point to the head object (again, this will be corrected in ECMAScript 5.)
Solve the problem of nested functions
In order to prevent this from being lost, you can use a scope chain in the parent function to save references to this. In the following code, using a variable called that, using its scope, we can better save the function context.
<!DOCTYPE html><html lang="en"><body><script> var myObject = { myProperty:'Icanseehelight', myMethod:function() { var that=this; //store a reference to this (iemyObject) in myMethod scope varhelperFunction function() { //childfunction var helperFunction function() { //childfunction //logs 'I can see the light' via scope chain because that=this console.log(that.myProperty); //logs 'I can see the light' console.log(this); // logs window object, if we don't use "that" }(); } } myObject.myMethod(); // invoke myMethod </script></body></html>Control the value of this
The value of this usually depends on the context in which the function is called (unless the keyword new is used, which will be introduced later), but you can use apply() or call() to specify the object this points to when a function is triggered to change/control the value of this. Using these two methods is like saying again: "Hey, call the X function, but let the Z object make this value." Doing so, the default value of this JavaScript will be changed.
Below, we create an object and a function, and then we trigger the function through call(), so this in the function points to myOjbect. This in myFunction function operates on myObject instead of the head object, so we change the object pointed to by this in myFunction.
<!DOCTYPE html><html lang="en"><body><script> var myObject = {}; var myFunction = function(param1, param2) { //setviacall()'this'points to my Object when function is invoked this.foo = param1; this.bar = param2; console.log(this); //logs Object{foo = 'foo', bar = 'bar'} }; myFunction.call(myObject, 'foo', 'bar'); // invoke function, set this value to myObject console.log(myObject) // logs Object {foo = 'foo', bar = 'bar'} </script></body></html>In the above example, we used call(), apply() can also be applied to the same usage. The difference between the two is how the parameters are passed to the function. Use call(), the parameters are separated by commas, and apply(), and the parameters are passed in an array. The following is the same code, but use apply().
<!DOCTYPE html><html lang="en"><body><script> var myObject = {}; var myFunction = function(param1, param2) { //set via apply(), this points to my Object when function is invoked this.foo=param1; this.bar=param2; console.log(this); // logs Object{foo='foo', bar='bar'} }; myFunction.apply(myObject, ['foo', 'bar']); // invoke function, set this value console.log(myObject); // logs Object {foo = 'foo', bar = 'bar'} </script></body></html>Use this in a custom constructor
When the function is triggered with the keyword new, the value of this is declared in the constructor to point to the instance itself. In other words: in the constructor, we can use this to specify the object before it is actually created. This seems to change this value to call() or apply().
Below, we construct a constructor Person, which points to the created object. When Person's object is created, this points to this object and puts the property name in the object, and the value is the parameter value (name) passed to this constructor.
<!DOCTYPE html><html lang="en"><body><script> var Person = function(name) { this.name = name || 'johndoe'; // this will refer to the instant created } var code = new Person('Cody Lindley'); // create an instance, based on Person constructor console.log(cody.name); // logs 'Cody Lindley' </script></body></html>In this way, when the constructor is triggered with the keyword new, this points to "object to be created". Then if we do not use the keyword new, the value of this will point to the context that triggers Person - this is the head object. Let's take a look at the code below.
<!DOCTYPE html><html lang="en"><body><script> var Person = function(name) { this.name=name||'johndoe'; } var code = Person('Cody Lindley'); // notice we did not use 'new' console.log(cody.name); // undefined, the value is actually set at window.name console.log(window.name); // logs 'Cody Lindley' </script></body></html>This pointing to the constructor instance within the prototype method
When a method is used as a prototype property of a constructor, this in this method points to an instance of the trigger method. Here, we have a Person() constructor, which requires the full name of the person. In order to obtain the full name, we add a whatIsMyFullName method to Person.prototype, and all Person instances inherit this method. This in this method points to the instance (and its properties) that triggered this method.
Below I created two Person objects (cody and lisa), and the inherited whatIsMyFullName method contains this point to this instance.
<!DOCTYPE html><html lang="en"><body><script> var Person = function(x){ if(x){this.fullName = x}; }; Person.prototype.whatIsMyFullName = function() { return this.fullName; // 'this' refers to the instance created from Person() } var code = new Person('cody lindley'); var lisa = new Person('lisa lindley'); // call the inherited whatIsMyFullName method, which uses this to refer to the instance console.log(cody.whatIsMyFullName(), lisa.whatIsMyFullName()); /* The prototype chain is still in effect, so if the instance does not have a fullName property, it will look for it in the prototype chain. Below, we add a fullName property to both the Person prototype and the Object prototype. See notes. */Object.prototype.fullName = 'John Doe'; var john = new Person(); // no argument is passed so fullName is not added to instance console.log(john.whatIsMyFullName()); // logs 'John Doe' </script></body></html>Use this in the method inside the prototype object, and this points to the instance. If the instance does not contain attributes, the prototype search begins.
hint
- If the object pointed to this does not contain the attributes you want to find, then the law that applies to any attributes is also applicable here, that is, the attributes will be "searched" along the prototype chain. So in our example, if the instance does not contain the fullName property, then the fullName will look for Person.prototype.fullName, and then Object.prototype.fullName.
To view more JavaScript syntax, you can follow: "JavaScript Reference Tutorial" and "JavaScript Code Style Guide". I also hope that everyone will support Wulin.com more.