Reading notes: Advanced JavaScript techniques (i)

Source: Internet
Author: User

I. Safe type detection

JavaScript built-in type detection mechanism is not completely reliable, due to browser or scope and other reasons, often error occurs. As you know, calling the ToString () method on any value returns a string in [object Native constructorname] format, with a [class] attribute inside each class that specifies the name of the constructor in the preceding string. For example

var value=[1,2,3,4,5]

Alert (Object.prototype.toString.call (value));//"[Object Array]"

Thus, we can create a function to determine the data type:

//ExampleSwitch(Object.prototype.toString.call (value)) { Case "[Object Array]": Alert ('Array');  Break;  Case "[Object Function]": Alert ("function");  Break;  Case "[Object RegExp]": Alert ("RegExp");  Break;  Case "[Object JSON]": Alert ("JSON")     Break}

Two. Scope-Safe constructors:

Let's look at one of the following examples

function Person (name,age) {

This.name=name;

This.age=age

}

Create an instance based on the constructor (this should be the case: Var person=new person ("Jame", 29))

var Person=person ("Jame", 29)

Alert (person.name)//js error, undefined

Alert (person.age)//js error, undefined

Alert (window.name)//jame

From the above, when we do not call the constructor person with the new operator, this is mapped to the object window. This is due to the late binding of the This object, which is bound at run time, so call the person () directly, the constructor is the seat of the normal function call, causing the error to occur. And because window's Name property identifies the link target and frame, accidental overwriting of the property here may cause other errors on the page. The solution to this problem is to create a scoped security constructor. As follows:

function Person (name,age) {if( Thisinstanceof person) {//detects if the This object is an instance of the correct type, if not, creates a new object and returns         This. name=name;  This. age=Age ; }Else{        return NewPerson (Name,age)}}varperson1=NewPerson ("Jame", -); alert (person1.name); //Jamealert (person1.age);// -Alert (Window.name)//"'Alert (window.age)//undefined

PS: When this pattern is implemented, the environment that can invoke the constructor is locked, and if you use the constructor to steal the inheritance of the schema and do not use the prototype chain, then this inheritance is likely to be corrupted as follows:

1 function Polygon (sides) {2    if( Thisinstanceof Polygon) {3        This. sides=sides;4        This. getarea=function () {5          return 0;6       }7}Else{8        return NewPolygon (sides);9    }Ten } One function rect (w,h) { APolygon.call ( This,2); -    This. width=W; -    This. height=h; the    This. getarea=function () { -     return  This. width* This. Height -   }     - } + varrect1=NewRect5,Ten) -Alert (rect.sides)//undefined

As previously understood, the result of rect.sides should be 2. Because we called the polygon method with the call method in the first line of the RECT function, but why is the result undefined?

In this code, the scope of the polygon constructor is secure, but the Rect constructor is not. After a new Rect instance is created, this instance should pass polygon. Call to inherit the sides property of polygon. However, because the scope of the Plygon function is secure and the This object is not an instance of polygon, a new polygon object is created and returned. This in rect does not change, and the value returned by Polygon.call does not have a knife, so there is no sides attribute in the RECT instance.

The solution is as follows:

function Polygon (sides) {if( Thisinstanceof Polygon) {       This. sides=sides;  This. getarea=function () {return 0; }   }Else{       return NewPolygon (sides); }}function rect (w,h) {Polygon.call ( This,2);  This. width=W;  This. height=h;  This. getarea=function () {return  This. width* This. Height}} Rect.prototype =new  Polygon () varrect1=NewRect5,Ten) alert (rect.sides)//2

Note The bold part of the code so that a rect instance is also a polygon instance, so polygon. Call will be executed as scheduled.

Three. function bindings

function bindings to create a function, you can call another function in a specific this environment with the specified parameters. This technique is often used in conjunction with the callback function and the event handler to preserve the code execution environment while passing the function seat variable, see the following example:

1 varHandler={2Message"Hello World",3Handleclick:function (Event){4Alert This. Message)5      }     6  }7  varBtn=document.getelementbyid ("my_btn");8Eventutil.addhandler (BTN,"Click", Handler.handleclick)//cross-browser event handling9  varEventutil={Ten addhandler:function (element,type,handler) { One        if(element.addeventlistener) { AElement.addeventlistener (Type,handler,false) -}Else if(element.attachevent) { -Element.attachevent (" on"+Type,handler) the}Else { -element[" on"+type]=Handler -        } -      }, + removehandler:function (element,type,handler) { -        if(element.removeeventlistener) { +Element.removeeventlistener (Type,handler,false) A}Else if(element.detachevent) { atElement.detachevent (" on"+Type,handler) -}Else { -element[" on"+type]=NULL  -        } -      }, -}

In this example, we have clicked on the button, and when the click occurs, we expect "Hello World", but the result is undefiend. The problem is that the Handler.handleclick environment is not saved, so the this object points to the DOM button instead of the handler, and we can fix the problem with a closure, as follows:

 varHandler={message:"Hello World", Handleclick:function (Event) {alert ( This. Message)} } varBtn=document.getelementbyid ("my_btn"); Eventutil.addhandler (btn,  "click", Function (event) {Handler.handleclick (  Event ); })

This solution uses a closure within the event handler to call Handler.handleclick () directly. Of course, the bedstead. Multiple closures may make the code difficult to understand and debug, so many JavaScript libraries implement a function that can be bound to a set environment, usually called bind (); A simple bind function takes over a function and environment and returns a function that invokes a given function in a given environment , and all parameters are passed intact. The syntax is as follows:

function bind (Fn,context) {

return function () {

Return fn.apply (context,arguments)

}

}

When a closure is created in bind, the closure uses apply () to invoke the passed-in function and pass the context object and argument (the argument is not bind () to the intrinsic function) to apply (). When the returned function is called, it executes the passed-in function in the given environment and gives all parameters. The bind () method for all functions defined for one months in ECMAScript 5, similar to the bind () method above, is to be passed in as the this worthy object. Browsers that support the native bind () method have Ie9+,firefox 4+,chrome. As long as a function pointer is passed in a worthwhile form, and the function must be executed in a particular environment, the utility of the bound function highlights 歘. Then the bound function has more overhead than the normal function, they need more memory, and because the multiple function calls are slightly slower, it is best to use them only when necessary.

The native invocation method is as follows:

 varHandler={message:"Hello World", Handleclick:function (Event) {alert ( This. message+":"+Event. Type)} } varBtn=document.getelementbyid ("my_btn"); Eventutil.addhandler (BTN,"Click", Handler.handleClick.bind (handler))

Here today, we'll look at lazy loading functions and the mysterious function of curry.

Reading notes: Advanced JavaScript techniques (i)

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.