There are many articles about the this keyword in js. I have read a few of them. The purpose of writing this article is to analyze the working principle of this from examples. I hope it will be helpful to everyone.
1. Basic:
function doSomething(){
alert(this.id);
}
alert(window.doSomething);//Proves that doSomething belongs to window
doSomething();//undefined
window.onload = function(){
document.getElementById("div2").onclick = doSomething;//div2
document.getElementById("div3").onclick = function(){doSomething( );}//undefined
}
1. For the doSomething function:
function doSomething(){
alert(this.id);
}
This function is a global function, this The global function actually belongs to window (can be accessed through window.doSomething). If it is called directly, then according to "this always refers to the "owner" of the function we're executing", then this in the function is window. However, window does not have an id attribute, so "undefined" is displayed;
2. Call this in the html element
This "undefined" will also be displayed, which is equivalent to the following code:
document.getElementById("div1").onclick = function(){doSomething();}
When div1 is clicked, the doSomething function belonging to window is called, so "undefined" is also displayed ;
3. Bind the event through js. After div2 is loaded:
document.getElementById("div2").onclick = doSomething;
When div2 is clicked, "div2" is displayed because the onclick of div2 is assigned a value. DoSomething is copied once. At this time, the copied function belongs to div2 and has nothing to do with doSomething belonging to window. When div2 is clicked, doSomething belonging to div2 will be triggered. This here refers to div2.
2. attachEvent and addEventListener
attachEvent is a method of binding events in IE. It will copy the corresponding function to the global world (that is, the owner of the response function is window), but in the DOM standard , when addEventListener binds an event, the owner of the copied response function is the object bound to the event
function doSomething(){
alert(this.id);
alert(this == window);
}
window.onload = function(){
var div1 = document.getElementById("div1");
if(div1.attachEvent){
div1.attachEvent("onclick",doSomething);
document.body.appendChild(document.createTextNode ("attachEvent"));
}else if(div1.addEventListener){
div1.addEventListener("click",doSomething,false);
document.body.appendChild(document.createTextNode("addEventListener "));
}else{
div.onclick = doSomething;
}
}
For function doSomething
function doSomething(){
alert(this.id);
alert( this == window);
}
1. Use attachEvent to bind to the click event of div1. doSometing will be copied to the window. At this time, this in doSomething refers to the window. When div1 is clicked, "undefined" and "true" will be displayed
2. Use addEventListener to bind the click event of div1. At this time, copy doSomething. The copied function belongs to div1, so when div1 is clicked, "div1" and "false" will be displayed
Note: http://www.quirksmode.org/js/this.html believes that attachEvent just uses a function reference. See the following code:
var obj = new Object();
obj.color = "black";
obj.showColor = function(){
alert(this.color);
alert(this == window);
}
obj.showColor();
var div1 = document.getElementById("div1");
div1.attachEvent("onclick",obj.showColor);
When div1 is clicked at this time, "undefined" and "true" will be displayed, if the attachEvent only refers to obj.showColor , then this should still refer to obj, but in fact this refers to window, so I think this is not a reference, but a copy to the global one.
3. Regarding the inheritance method of object impersonation
1. The difference between new and not new
For the following functions
function ClassA(sColor){
this.color = sColor;
this.sayColor = function() {
alert(this.color);
}
}
Is this a class or a function? It's up to you!
If you think this is a function, then we can call it like this:
ClassA("red");
"red" is a parameter passed, in ClassA This refers to window, of course, so now window has a color attribute and a sayColor method, and color has the value "red".
This is to call sayColor or window.sayColor to display "red";
window.sayColor();
If you think this is a class, Then we should use it like this:
var obj = new ClassA("red");
The appearance of the new keyword adds a lot of content to the above code: First, create an Object instance , then point this in ClassA to the created Object, and finally return this Object, so the returned Object is assigned to obj. So we can say that this points to obj, obj has the color attribute and the sayColor method, and the color attribute value is "red".
2. Function owener
function showId(){
alert(this.id);
}
window.onload = function(){
var div1 = document.getElementById("div1");
div1.onclick = showId;
div1.show = showId;
div1.show();
var obj = new Object();
obj.id = "obj";
obj .show = showId;
obj.show();
}
We can assign the showId function to the click event, or to any attribute of any object. This will also copy the showId method, so when we call the div1.show method, this points to div1, and when we call obj.show, this points to obj.
3. The principle of object impersonation
The following code is inheritance implemented through the object impersonation method
function ClassA(sColor){
this.color = sColor;
this.sayColor = function(){
alert(this. color);
}
}
function ClassB(sColor,sName){
this.newMethod = ClassA;
this.newMethod(sColor);
delete this. newMethod;
this.name = sName;
this.sayName = function(){
alert(this.name);
}
}
var objB = new ClassB("color of objB","name of objB");
objB.sayColor();
objB is an instance of ClassB. How does objB have the color attribute and sayColor method?
First look at the instantiation code:
var objB = new ClassB("color of objB","name of objB");
Here ClassB is a class , of course this in ClassB refers to the object objB;
In ClassB, the first three lines of code will use ClassA, then ClassA is regarded as a function, not a class.
If we call the ClassA function directly, then obviously, this in ClassA refers to the window object, so we first copy ClassA to the newMethod attribute of objB (this.newMethod = ClassA),
Then call this.newMethod. This is because the owener of this method has obviously become this, and this in ClassB currently refers to objB, so at this time it is in ClassA (strictly speaking, it is in newMethod , because this is copied and already has two methods with ClassA) this refers to objB. In this way, through the call of newMethod, the color attribute and sayColor method are assigned to objB. Using the call and apply methods to implement inheritance is actually a principle. Call and apply can be regarded as methods to change the owner of the method, and the first three lines of code in ClassB here play this role.
4. Class.create in prototype1.6
The Class.create method in prototype1.6 is roughly as follows:
var Class = {
create: function() {
//
function klass() {
this.initialize.apply(this, arguments);
}
//
for (var i = 0; i < properties.length; i )
klass.addMethods(properties[i]);
//
return klass;
}
};
in use It looks like this:
var Person = Class.create({
initialize:function(name){
this.name = name;
},
say:function(message){
alert(this.name " :" message);
}
});
var aPerson = new Person("name1");
aPerson.say("hello1");
Person is actually the klass returned by the Class.create method (klass is a local variable in Class.create, a function), and the parameters passed by Class.create (initialize method and say method) are passed to create In the properties array in the method and let the klass prototype have these methods through the addMethods method. So the most critical point and the most difficult to understand is: what exactly does this in klass refer to. If you think about it carefully, it is not difficult to get the answer. Person is actually klass, and when we instantiate the Person object, we use the new keyword:
var aPerson = new Person("name1") ;
This is equivalent to
var aPerson = new klass("name1");
Although klass cannot be accessed from the outside, it can be easily accessed in this way To explain the problem, klass is a class rather than a simple function (we think so because the new keyword is used), then this in klass refers to the declared instance, here it is aPerson, aPerson passes the prototype of klass You can have an initialize method and a say method. During the new process, the code in klass will also be executed, so initialize will be executed when instantiated, that is, the constructor. (Both thiss in klass refer to aPerson. Why do you need to call it once through apply? This is mainly to pass the parameters of the constructor. Using the apply method, an indefinite number of parameters can be conveniently passed to initialize through an array. Method. )
5. Analyze a few more examples
Let me analyze the examples I saw in other articles:
1. Run as follows Code
function OuterFoo(){
this.Name = 'Outer Name';
function InnerFoo(){
var Name = 'Inner Name';
alert(Name ', ' this.Name);
}
return InnerFoo;
}
OuterFoo()();
The displayed result is "Inner Name, Outer Name"
OuterFoo is a function (not a class), then the first sentence
this.Name = 'Outer Name'; This in
refers to the window object, so after OuterFoo() window.Name = 'Outer Name';
and returns InnerFoo. At this time, InnerFoo is also a function (not a class ), when executing InnerFoo, this also refers to window, so the value of this.Name in InnerFoo is "Outer Name" (window.Name acts as a transfer station, allowing OuterFoo to pass the value "Outer Name" to InnerFoo ), and the value of Name is the local variable "Inner Name"
2. Run the following code
function JSClass(){
this.m_Text = 'division element';
this.m_Element = document.createElement( 'DIV');
this.m_Element.innerHTML = this.m_Text;
if(this.m_Element.attachEvent)
this.m_Element.attachEvent('onclick', this.ToString);
else if(this.m_Element.addEventListener)
this.m_Element.addEventListener('click', this.ToString,false);
else
this.m_Element.onclick = this.ToString;
}
JSClass.prototype.Render = function(){
document.body.appendChild(this.m_Element);
}
JSClass.prototype.ToString = function (){
alert(this.m_Text);
alert(this == window);
}
window.onload = function(){
var jc = new JSClass ();
jc.Render();
jc.ToString();
}
Clicking "division element" will display "undefined", which is also required under IE Displays "true", and other browsers also display "false".
There is nothing to say about instance declaration and calling instance methods. The click event of an element is bound to an instance method, so the method bound to it through addEventListener is copied, so this refers to html element, this element does not have the m_Text attribute (the m_Text attribute belongs to the instance of JSClass, that is, to jc), so clicking on the element displays undefined. The event bound to attachEvent will copy the function to the global world. At this time, this refers to the window object. Clicking on the element also displays "undefined". Only when the jc.ToString() method is called, this refers to the jc object. Because jc owns m_Text, it can display the "division element".
6. Summary
How to quickly find the object pointed to by this in a code environment? I want to pay attention to the following three aspects:
1. It is necessary to clearly know whether each step of the function is a copy or a reference (call)
2. It is necessary to clearly know who the owner of the function is
3. For a function, we need to figure out whether we are using it as a function or as a class
Supplement:
1. Functions can be directly defined on both instances and classes
2. You cannot use prototype to define functions on instances, you can only use prototype to define functions on classes
3. Functions defined directly on the class cannot use this to access the properties of the object
4. On the prototype of the class Functions created can use this, functions defined within a class can use this, functions created on object instances can use this
window.alert=function (msg)
{
document.write(msg "
");
}
function say()
{
this.f="props";
this.func3=function(){alert("f3," this.f);}
}
say .func1=function(){alert("func1," this.f);}; //Error, functions directly defined on the class cannot be used this
say.prototype.func2=function(){alert(" func2," this.f);}
say.func1();
(new say()).func2();
say.func2(); //Error, defined in prototype Function, the object must be instantiated before calling
say.func3(); //Error, the function defined on the class must be instantiated before calling
(new say()).func3();
var obj={
fld1:10,
func1:function(msg){alert(msg);},
func4:function(){alert(this.fld1);}
}
obj.prototype.func=function(){alert("func");}; //Error prototype cannot be used to define objects on instance objects
obj.func2=function(){alert("func2," this .fld1);}; //ok, functions defined directly on the instance can use this to access the properties of the object
alert(obj.fld1);
obj.func1("func1");
obj .func2();
obj.func4();
Javascript 사용법 요약
http://www.jb51.net/article/16863.htm
JavaScript에 대한 심층적인 이해
http://www.jb51.net/article/19425.htm
객체 지향에 대한 자세한 설명은 JAVASCRIPT
http://www.jb51.net/article/17584.htm
이 포인터를 자바스크립트로 사용하세요
http://www.jb51.net/article/19434.htm
자바스크립트에서 이 키워드를 사용하는 방법에 대한 자세한 설명
http://www.jb51.net/article/7954.htm