Dynamic this in javascript and dynamic binding of instance code _ javascript skills

Source: Internet
Author: User
Javascript is a dynamic language, and dynamicthis is the most obvious. It generally exists as a function caller. In javascript, all links can exist as an associated array element of an object. Then the function is split into two parts and stored in the object. One is the function name (key), the other is the function body (value ), this in a function generally points to the object where the function is located. However, this is normal. When calling a function globally, we do not see the caller, or it is a window. However, after the function is declared, it is not bound to any object, so we can use the call apply method to set the caller.

A simple example:
[Script]
Script
Window. name = "window ";
Var run = function (){
Alert ("My name is" + this. name );
}
Run ();
Script
[/Html]
Here, you cannot say that run exists as an attribute of window, but it is indeed called by the window attribute. In essence, most of the things exposed to the top layer are taken over by window. When they need to be called, they are copied to the window object (but in IE window does not inherit the object), So window ['xxx'] and window are available. xxx performance differences. This is an internal implementation.
In another example, bind to a specific object

Script window. name = "window"; object = {name: "object", run: function () {alert ("My name is" + this. name) ;}}; object. run (); script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


The answer is obviously easy to see. this is always the caller. But what if it is more complex?

Script window. name = "window"; object = {name: "object", run: function () {var inner = function () {alert ("My name is" + this. name) ;}inner () ;}}; object. run (); script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


Although it is defined inside the object, although it is defined inside the run function, it is neither an object nor a run, because it is neither an object attribute nor a run attribute. It is loose in the scope of run and cannot be called by the first two. It is only saved by window. Window and other native objects are immersed in the interior of all scripts and are pervasive. It is incumbent upon us to make contributions wherever it is needed. But we usually don't need it to help, which requires the call and apply tools.

Script window. name = "window"; var object = {name: "object", run: function () {inner = function () {alert (this. name);} inner. call (this) ;}} object. run (); script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


The difference between call and apply lies in the form of parameters after the first parameter. call is made one by one, and aplly is put on an array. When the parameters are not clear, we can use arguments and Array. slice is easy to handle.

Script window. name = "Window"; var cat = {name: "Cat"}; var dog = {name: "Dog", sound: function (word) {alert (this. name + word) ;}}; dog. sound ("is pooping"); dog. sound. call (window, "is banking"); dog. sound. call (dog, "is banking"); dog. sound. apply (cat, ["miaowing"]); script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


The Prototype developer developed a very famous function, bind! Below is one of its simplest versions:

The Code is as follows:


Var bind = function (context, fn ){
Return function (){
Return fn. apply (context, arguments );
}
}


Script window. name = "Window"; var cat = {name: "Cat"}; var dog = {name: "Dog", sound: function (word) {alert (this. name + word) ;}}; var bind = function (context, fn) {return function () {return fn. apply (context, arguments) ;}} var sound2 = bind (window, dog. sound); sound2 ("is banking"); var sound3 = bind (cat, dog. sound); sound3 ("miaowing") script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


However, we recommend that you use the following versions to cope with more complex situations.

The Code is as follows:


Function bind (context, fn ){
Var args = Array. prototype. slice. call (arguments, 2 );
Return args. length = 0? Function (){
Return fn. apply (context, arguments );
}: Function (){
Return fn. apply (context, args. concat. apply (args, arguments ));
};
};


It also has a twin brother called bindAsEventListener, which binds the event object. There is nothing to say.

The Code is as follows:


Var bindAsEventListener = function (context, fn ){
Return function (e ){
Return fn. call (context, (e | window. event ));
}
}


Prototype version

The Code is as follows:


Function. prototype. bind = function (){
If (arguments. length <2 & (typeof arguments [0] === 'undefined '))
Return this;
Var _ slice = Array. prototype. slice
Var _ method = this, args = _ slice. call (arguments, 0), context = args. shift ();
Return function (){
Return _ method. apply (context, args. concat (_ slice. call (arguments, 0 )));
}
}


Script Function. prototype. bind = function () {if (arguments. length <2 & (typeof arguments [0] === 'undefined') return this; var _ slice = Array. prototype. slice var _ method = this, args = _ slice. call (arguments, 0), context = args. shift (); return function () {return _ method. apply (context, args. concat (_ slice. call (arguments, 0);} var sound2 = dog. sound. bind (window); sound2 ("is banking"); var sound3 = dog. sound. bind (cat); sound3 ("miaowing") script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


The bind Function is so useful that google has already added it to the Function prototype (In addition, inherits, mixin, and partial ).

The Code is as follows:


// In chrome
Var a = function (){};
Alert (a. bind)


If there is a binding, there will be anti-binding, or it is better to strip! For example, we cannot retrieve native objects by traversing their generalization methods.

Script for (var I in Array) {alert (I + ":" + Array [I])} for (var I in Array. prototype) {alert (I + ":" + Array. prototype [I])} script
[Ctrl + A select all Note: If you need to introduce external Js, You need to refresh it to execute]


To retrieve them, you need:

The Code is as follows:


Var _ slice = Array. prototype. slice;
Function unbind (fn) {// The first step is to obtain the generalization method.
Return function (context) {// The second part uses the corresponding native object to call it again!
Return fn. apply (context, _ slice. call (arguments, 1 ));
};
};


The example has been provided before. Please refer to the article
Summary:
The value of this depends on the method in which the function is called. There are four types of values,
If a function is an object property and the function is called, the value of this is the object. If the function call expression contains periods (.) or [], the value of this is an object before periods (.) or. For example, in myObj. func AND myObj ["func"], this is myObj when func is called.
If a function is not an object attribute, the value of this is a global object when the function is called. When a function contains an internal function, if you do not understand the correct meaning of this, it is easy to cause errors. This is because the internal function's this value is different from its external function's this value. The solution is to save the this value of the external function in a variable and use it in the internal function to find the variable.
If new is used before a function, a new object will be created and the funtion will be called. The value of this is the newly created object. For example, function User (name) {this. name = name}; var user1 = new User ("Alex");. By calling new User ("Alex"), a new object is created and referenced as user1, the User function will also be called, and the property named name will be set in the user1 object. Its value is Alex.
You can use the apply and call methods of function to specify the value of this when it is called. The first parameter of apply and call is the value of this to be specified. As they exist, we can create various useful functions.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.