Javascript this pointer _javascript tips

Source: Internet
Author: User
Tags tag name

Objective

JavaScript is an object-based dynamic language, that is, everything is an object, and a typical example is that a function is also considered an ordinary object. Javascript can achieve object-oriented programming through certain design patterns, in which this "pointer" is an important feature to implement object-oriented. But this is also one of the features of JavaScript that is very easy to understand and then to err on the wrong. This is especially true for comrades who have been in contact with static language for quite some time.

Example description

Let's take a look at one of the simplest examples:

<Type= "Text/javascript"function Sayhi () {alert (script>    

This code is very simple, we have defined a global string object name and function object Sayhi. Run will pop up a greeting dialog box, "Hello, my name is Kevin Yang."

Let's change this code a little bit:

<Type= "Text/javascript"function Sayhi () {alert (script>    

The difference between this piece of code and the previous code is that the Sayhi function adds this. prefix when using name. The running result is the same as the above one. This indicates that the THIS.name reference is also a global name object.

We're not saying that the function is also a normal object and can be used as a normal variable. Let's change the above code again:

<Type= "Text/javascript"function Sayhi () {alert (script>    

This time, we create a global object person and assign the Sayhi function object to the SayHello property of the Person object. The results of the operation are as follows:

This time, the content of the greeting is a bit of a nonsense, we found that THIS.name has become undefined. This indicates that the THIS.name object was not found when executing inside the SayHello function. What if we redefine the person object and add a name attribute to it?

var person = {name:' Marry '};

Running code found that the greeting of the "person" has changed:

Do you see the point of the road?

The guiding principle for judging this pointer

Inside JavaScript, this pointer represents the owner of the object that executes the current code.

In the example above, we can see that the for the first time, we defined a global function object Sayhi and executed this function, which uses the This keyword internally, so the object executing this line of code is SAYHI (the embodiment of all objects), and sayhi is defined in the global scope. In fact, the so-called global object in JavaScript is nothing more than a property defined under the root object of window. Therefore, the owner of the Sayhi is the Window object. That is, in a global scope, you can refer to the object by using the name directly, or you can refer to the same object by Window.name. Thus this.name can be translated into Window.name .

Let's look at the second example of this. We define an object of person and define its SayHello property to point to the Sayhi global object. So this time, When we run Person.sayhello, this is where the code belongs to SayHello (in fact, Sayhi and SayHello are just like two pointers, the object is actually the same), and the owner of the SayHello object is person. For the first time, the person does not have the Name property, so the pop-up dialog box is this.name refers to the undefined object (all of the variables declared in JavaScript that are not defined point to the undefined object ) And the second time we added the name attribute to the definition of person, then the this.name point of nature is the string we defined.

After understanding what has been said above, we have transformed the last example above into an object-oriented code.

<script = "Text/javascript" > function Sayhi () {alert ( "Hello, my name is" + this.name);} function person (name) {this.name = name;} Person.prototype.sayHello = Sayhi; var marry = new person ( "marry"); Marry.sayhello () var kevin = new person ( "Kevin"); Kevin.sayhello (); script>           

In the above code, we define a person's "class" (which is actually an object), and then define the SayHello attribute in the prototype of the class, which is equivalent to the concept of a static member variable in C + + , to point to the global Sayhi object. Run code we can see that marry and Kevin have succeeded in saying hello to us.

In this code there are two things to think about, one is new we are very familiar with, but here in the end what does the operation? The other is, when performing sayhello here, why does this pointer correctly point to marry and Kevin objects?

Let's do a "translation" of the actions that define "class" and instantiate the class object:

<Type= "Text/javascript"function Sayhi () {alert (var marry = person (var kevin = person (  Script>      

Of course this code does not execute correctly, but it can help you understand the process better.

When we instantiate a "class" object using the New keyword, the JavaScript engine defines a new object inside the object and stores it in the this pointer. All the code inside this object that uses this is actually pointing to this new object. such as THIS.name = name, is actually assigning the name object in the parameter to the newly created object. The JavaScript engine returns this object to you after the function object is executed, so the name of the object that the Marry variable obtains is "Marry", and the name of the object that the Kevin variable gets is indeed "Kevin".

A situation that is easy to misuse

After understanding the this pointer, let's take a look at some of the situations where it is easy to misuse this pointer.

Example 1--event handlers for inline-bound DOM elements

<Type= "Text/javascript"function Sayhi () {alert (script<IDtypevalue onclick= "sayhi ()">          

In this example code, we bind the button's Click event and expect to print the tag name of the click Element in the pop-up dialog box. But the results of the operation are:

That is, the this pointer does not point to the INPUT element. This is because when you use an inline-bound event-handler function for a DOM element, the following code is actually executed:

<Type= "Text/javascript"> document.getElementById (script>    

In this case , the ownership of the Sayhi function object is not transferred or belongs to window. with the guidelines set out above we can well understand why this.tagname is undefined.

So what if we're going to refer to the element itself?

We know that the onclick function belongs to the btntest element, so inside this function, this pointer is pointing to this DOM object, so we just need to pass this as a parameter to the Sayhi.

<type= ' text/javascript 'function Sayhi (EL) {alert (script<IDtypevalue onclick= "Sayhi (This)">          

The equivalent code is as follows:

<Type= "Text/javascript"> document.getElementById (function () {sayhi (script> 

Example 2--temporary variable causes this pointer to be lost

<script = "Text/javascript" > var Utility = {Decode:function (str) {return unescape (str);}, Getcookie:function (key) {//... Omit the code that extracts the cookie string var value =  "I%27m%20a%20cookie"; return this.decode (value); Alert (Utility.getcookie (script>   

We write a little bit of the size of the JS library, generally will encapsulate a utility class, and then some commonly used functions as utility class properties, such as the client often used GetCookie functions and decoding functions. If each function is independent of each other, then it's okay to do it, the problem is that functions sometimes refer to each other. The GetCookie function above, for example, decode the string extracted from the Document.cookie and then returns. If we call through Utility.getcookie, then there is no problem, and we know that the this pointer inside the GetCookie is pointing to the utility object, and the utility object contains the decode attribute. The code can be executed successfully.

But did someone accidentally use utility objects like this?

<Type= "Text/javascript"var getcookie = Utility.getcookie; alert (getcookiescript> 

Running code this time throws an exception "This.decode is not a function". Using the guidelines we talked about above, it's well understood, because at this point the Utility.getcookie object is assigned to the temporary variable GetCookie, and the temporary variable belongs to the Window object-except that the outside world cannot directly refer to the JavaScript engine- So the this pointer inside the GetCookie function is pointing to the Window object, and the Window object does not define a decode function object, so it throws such an exception.

The problem is the transfer of this pointer caused by the introduction of a temporary variable. There are several ways to resolve this problem:

    • Do not introduce temporary variables, use Utility.getcookie to invoke each use
    • The GetCookie function uses Utility.decode to explicitly reference the Decode object without an implicit reference through the This pointer (this method is not available if the utility is an instantiated object, which is generated through new)
    • Use the funtion.apply or Function.call function to specify the this pointer

The first two kinds are better understood, the third need to mention. Because the this pointer's point is easily lost, JavaScript provides two similar functions apply and call to allow the function to explicitly specify the this pointer when called.

The revised code is as follows:

<Type= "Text/javascript"var getcookie = Utility.getcookie; alert (Getcookie.call Utility," Identity ")); Alert (getcookie.apply utility,[script>     

There are only grammatical differences between call and apply, and there is no functional difference.

The this pointer is missing when the example 3--function argument is passed

Let's take a look at the problem code:

<type= ' text/javascript 'var person = {name:' Kevin Yang ', Sayhi:function () {alert ("Hello, I am "+script>       

This code expects the visitor to say hello to the visitor after 5 seconds of entering the page. The settimeout function receives a function as an argument and executes the function at the specified trigger time. However, when we wait for 5 seconds, the pop-up dialog box shows the this.name is undefined.

In fact, this problem is similar to the one in the previous example, because of the problem caused by a temporary variable. When we execute the function, if the function has arguments, then the JavaScript engine creates a temporary variable and copies the incoming arguments (note that JavaScript is a value-passing, no reference-passing concept) to this temporary variable. That is, the whole process is the same as the above we define a getcookie temporary variable, and then assign the Utility.getcookie to this temporary variable. But in this example, the bug caused by the temporary variable is easily overlooked.

Function Object argument

Many frameworks already have a solution to the problem of this pointer loss caused by a function passing as a parameter.

Prototype solution--use the Bind method to encapsulate the function before passing the argument and return the encapsulated object

<type= ' text/javascript 'var person = {name:' Kevin Yang ', Sayhi:function () {alert ("Hello, I am "+script>       

The implementation of the Bind method actually uses JavaScript, another advanced feature-closures. Let's take a look at the source code:

function bind () {if (Arguments.length < 2 & & Arguments[0] = = undefined) return var __method = this, args = $A (arguments), object = Args.shift (); return function () {return __method.apply ( object, Args.concat ($A (arguments)); } }

The this pointer is first stored in the function's internal temporary variable, and then the temporary variable is referenced in the returned function object to form a closure.

Microsoft's AJAX Library offers a solution-building a delegate object

<type= ' text/javascript 'var person = {name:' Kevin Yang ', Sayhi:function () {alert ("Hello, I am "+script>       

In fact, the prototype is essentially the same way.

The famous ExtJS Library solution uses the same technique as Microsoft.

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.