JavaScript Ninja cheats--prototypes

Source: Internet
Author: User
Tags assert function prototype instance method hasownproperty

Summary : This blog mainly introduces the prototype of JavaScript

1. Instantiation of objects

-Priority of initialization

The priority of the initialization operation is as follows:

Properties added to an object instance by prototype

Properties added to an object instance within a constructor function

The precedence of the binding operations within the constructor is always higher than the precedence of the binding operations on the prototype. Because the this context of the constructor points to the instance itself, we can initialize the core content within the constructor.

-Reconcile References

The following code observes the behavior of the prototype when it changes:

function Ninja () {    thistrue;} var New  function() {    returnthis. swung;}; ASSERT (Ninja.swingsword (),    "Method exists, even out of order.");

In this example, you define a constructor, ninja, and use it to create an object instance. Then add a method to the prototype and run the test. The results show that the properties on the prototype are not copied elsewhere, but are attached to the newly created object and can be run in harmony with the property references of the object itself.

Each object in JavaScript has an implicit property named constructor that references the constructor that created the object. Because prototype is a property of the constructor, each object has a way to find its own prototype.

When you enter the Ninja.constructor reference in the console, we see the desired ninja () function because the object was created using this function as a constructor. A deeper Ninja.constructor.prototype.swingSword reference illustrates how we can access the prototype properties of an object instance in this way.

Change the above example as follows:

functionNinja () { This. swung =true;  This. Swingsword =function(){        return! This. Swung; };}varNinja =NewNinja (); Ninja.prototype.swingSword=function(){    return  This. swung;}; Console.assert (Ninja.swingsword (),"Called the instance method, not the prototype method.");

In this example, we redefine an instance method with the same name as the prototype method, and then create the prototype method after the constructor executes. Tests show that, even after instantiating an object and adding methods to the prototype method, the instance method will prioritize the method on the prototype.

-Determine object type by constructor

The constructor for the object can be obtained through the constructor property. At any time, we can re-reference the constructor and even use it for type checking, as shown in the following example:

 function   Ninja () {}  var  Ninja = new   Ninja (); Assert ( typeof  Ninja = = "Object"  "the type of the instance is object."   Ninja,  Instanceof identifies the constructor.  == Ninja,  " The Ninja object is created by the Ninja function. ");  

Using the typeof operator to determine the type of the instance is not very useful, it just tells us that the instance is just an object, because the check result always returns object. And the instanceof operator is really useful, and the operator tells us a very clear way to determine whether an instance is created by a particular function constructor.

In addition, we can also use the constructor property, which we now know is added to all instances as a reference to the original function that created the object. With this property, we can verify the origin of the instance.

function Ninja () {} var New Ninja (); var New  instanceof Ninja, "It ' s a ninja!"  !== ninja2, "but not the same ninja!");

Define a constructor, and then use the constructor to create an instance. The second instance is then created using the constructor property of the instance. The test results show that the second Ninja object was created successfully, and that the variable pointed to not the same instance.

-Inheritance and prototype chain

Another function of the instanceof operator is as a form of object inheritance. The following code: Using a prototype to implement inheritance

functionPerson () {}person.prototype.dance=function(){};functionNinja () {}ninja.prototype={dance:Person.prototype.dance};varNinja =NewNinja (); Assert (NinjainstanceofNinja,"Ninja receives functionality from the Ninja prototype"); Assert (NinjainstanceofPerson, "... and the person prototype"); Assert (NinjainstanceofObject, "... and the object Prototype");

Since the function prototype is just an object, there are many functions that can be replicated to achieve the purpose of inheritance. In the preceding code, you first define a person, and then you define a ninja. Because Ninja is obviously also a person, we want Ninja to inherit the attributes of people as well. We tried to replicate the dance property method of the person archetype to the Ninja prototype as a method with the same name to implement the inheritance function. The test results show that this is replication rather than inheritance.

What we really want to achieve is a prototype chain, the best way to create such a prototype chain is to use an instance of an object as a prototype for another object: Subclass.prototype = new superclass ();

For example: ninja.prototype = new Person (); This will maintain the prototype chain, because the prototype of the subclass instance will be an instance of superclass, which not only has a prototype, but also holds all the properties of superclass, and the prototype points to an instance of its own superclass.

function   Person () {}person.prototype.dance  = function   () {};  function   Ninja () {}ninja.prototype  = new   person ();  var  ninja = new   Ninja (); Assert (Ninja  instanceof   Ninja,  Ninja receives functionality from the Ninja prototype ""; Assert (Ninja ins taceof person,  ... and the person prototype ""; assert ( typeof  ninja.dance = = "function", "... and can dance!"); 

The code above takes an instance of person as a prototype of ninja. By performing a instanceof operation, you can determine whether a function inherits the functionality of any object in its prototype chain. Another good side effect of this prototype inheritance is that all the inherited functions in the prototype are updated in real time.

It makes sense that all Ost JavaScript object constructors (such as Object, Array, String, number, REGEXP, Function) have prototype properties that can be manipulated and extended, because each object constructor is itself a function.

2. Problematic traps

-Extension Objects

The serious mistake we may make is to extend the native object.prototype. The reason for this is that when you extend the prototype, all of the objects accept these extra attributes. This problem is especially serious when we iterate over the properties of the object, and the appearance of new attributes can lead to a variety of unexpected behaviors.

function () {    var keys = [];      for (varin this) Keys.push (p);     return keys;}; var obj = {a:1, b:2, c:3= =3    ,"There is three prototypes in this object.");

JavaScript provides a method named hasOwnProperty () that can be used to determine whether a property is defined on an object instance or imported from a prototype.

 object.prototype.keys =  function   { var  keys = [];  for  (var  i in  )  if  (this  .hasownproperty (i)) Keys.push    (i);  return   keys;};  var  obj = {a:1, b:2, C:3};assert (Obj.keys (). Length  = = 3" there is three properties in this object. ");  

We redefined the method, ignoring the non-instance properties.

-Extended numbers

In addition to the object we studied in the previous section, it is relatively safe to extend the prototypes of other OST objects. However, another problematic native object is number.

Add a method to the number prototype

function (num) {    return this + num;} var n = 5; assert (N.add (3) = = 8, "It works when the numberwas in    a variable." ); Assert ((5). Add (3) = = 8, "Also works if a numberis wrapped in    parentheses." ); Assert (5.add (3) = =8    ,"What is about a literal?");

Here, we define a new method, add () on number, which takes a parameter and adds the parameter to its own value before returning. The new method is then validated in a variety of ways. However, when we try to load the page in the browser, the page does not load. In general, unless you really need it, it's best to avoid scaling on number prototypes.

-Instantiation issues

Functions are used for two purposes: as "normal" functions, as well as as constructors. So it is easy to confuse usage.

function User (First, last) {    this. Name = First + "" + Last ;}  var user = User ("Ichigo", "Kurosaki""user instantiated"= = "Ichigo Kurosaki",    /c11> "User name correctly assigned");

In the code above, we define a user class whose constructors accept the first and last arguments and concatenate them into a full name, and then assign the value to the Name property. We then create an instance of the class that assigns a value to the user variable, tests whether the object is instantiated, and whether the constructor is executed correctly.

However, a serious error occurred while running the code. The reason is that the new operator is not called on the user () function. In this case, the absence of the new operator causes the function to be called as a normal function, not a constructor, and no new object is instantiated. In addition, constructor functions that are called as normal functions have subtle side effects, such as polluting the current scope, leading to more unexpected results. The following code accidentally introduces a variable into the global namespace:

function User (First, last) {    this. Name = First + "" + Last ;}  var name = "Rukia"; var user = User ("Ichigo", "Kurosaki"= = "Rukia", "Nameis set to    Rukia.");

The following code can tell if a function is called as a constructor:

function Test () {    returnthisinstanceof  Arguments.callee;} ASSERT (! Test (), "We didn ' t instantiate, so it returns false." ); assert (new Test (), "We did instantiate, returning true.");

When the function is executed as a constructor, the expression:

this. instanceof Arguments.callee

The result of this is true, which returns true if executed as a normal function.

Fix the problem on the caller

functionUser (First, last) {if(! ( This instanceofArguments.callee)) {        return NewUser (First, last); }     This. Name = First + "" +Last ;}varName = "Rukia";varuser = User ("Ichigo", "Kurosaki"); Assert (name= = "Rukia", "Name is set to Rukia."); Assert (UserinstanceofUser, "User instantiated"); assert (User.Name= = "Ichigo Kurosaki",    "User name correctly assigned");

Determines whether the function is called in an incorrect manner, and if so, instantiates the user itself and returns it as the result of the function. The result of this is that, regardless of whether we call the function as a normal function, we will eventually return a user instance.

JavaScript Ninja cheats--prototypes

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.