Learn the prototype,getprototypeof and __proto___javascript skills of JavaScript with me

Source: Internet
Author: User
Tags inheritance

A deep understanding of prototype, getprototypeof and _ proto _

Prototype,getpropertyof and _ proto _ are three methods used to access the prototype. They are named in a similar way so it is easy to confuse.

They are used in the following ways:

    • C.prototype: Typically used to build its prototype inheritance object for a type. For example, C.prototype = xxx, this will let the object using new C () the prototype object is XXX. Of course, using Obj.prototype can also get the prototype object of obj.
    • GetPropertyOf:Object.getPropertyOf (obj) is the standard method used in ES5 to get the prototype object of the Obj object.
    • _ proto _: Obj._ Proto _ is a non-standard method for obtaining the prototype object of obj object.

To fully understand the various ways of acquiring prototypes, here's an example:

function User (name, PasswordHash) { 
 this.name = name; 
 This.passwordhash = PasswordHash; 
} 
User.prototype.toString = function () {return 
 "[User" + THIS.name + "]"; 
User.prototype.checkPassword = function (password) {return 
 hash (password) = = This.passwordhash; 
var u = new User ("Sfalken", "0ef33ae791068ec64b502d6cb0191387"); 

The user function has a default prototype property, and the value of the property is an empty object. In the above example, two methods are added to the prototype object, namely, ToString and Checkpassword. When the user constructor is invoked to get a new object U, its prototype object is automatically assigned to the User.prototype object. That is, U.prototype = = User.prototype returns True.

The User function, User.prototype, the relationship between the object u can be represented as follows:

The arrows in the figure above represent an inheritance relationship. When you access some properties of a U object, you first try to read the properties on the U object, and if you do not have this property on the U object, you will find its prototype object.

For example, when calling U.checkpassword (), because the Checkpassword is defined on its prototype object, the property cannot be found on the U object, and the lookup order is on the prototype of U u-> U.prototype (User.prototype).

As mentioned earlier, the Getprototypeof method is the standard method used in ES5 to get the prototype object of an object. So:

object.getprototypeof (u) = = User.prototype; True 

In some environments, a nonstandard _ proto _ property is provided to get the prototype object of an object. This property can be used temporarily as an alternative when the environment does not provide a ES5 standard method Getprototypeof method. You can use the following code to test your environment for support _ proto _:

 
 

So in JavaScript, the concept of a class is done together by constructors (User) and a prototype object (User.prototype) that is used to share methods between instances. Constructors are responsible for constructing properties specific to each object, such as the name and password properties in the example above. The prototype object is responsible for storing attributes common to all objects, such as the Checkpassword and ToString methods in the example above. As shown in the following picture:

Second, get the object priority to use Object.getprototypeof, rather than _ proto _

In ES5, object.getprototypeof is introduced as a standard API for acquiring object prototype objects. However, in many execution environments, a special _ proto _ attribute is also provided to achieve the same purpose.

Because not all environments provide this _ proto _ attribute, and each environment is implemented differently, some results may be inconsistent, for example, for objects that have null prototypes:

In some environments 
var empty = object.create (null);//Object with no prototype 
"_proto _" in empty;//False (in some ENVI ronments) 

//In some environments 
var empty = object.create (null);//Object with no prototype 
"_proto_" in empty;//True ( In some environments) 

Therefore, when the Object.getprototypeof method is supported in the environment, it is used preferentially. Even if it is not supported, you can implement one:

if (typeof object.getprototypeof = = "undefined") { 
 object.getprototypeof = function (obj) { 
  var t = typeof Obj;
   if (!obj | | (t!== "Object" && t!== "function")) { 
   throw new TypeError ("Not a object"); 
  } 
  return obj._proto_;} 
 

The code above first checks the current environment, and if object.getprototypeof is already supported, the definition is not repeated.

Third, never to modify _ proto _

Compared with object.getprototypeof, _ proto _ 's special place is also reflected in its ability to modify an object's prototype inheritance chain. Because it is an attribute, it can be set up in addition to the operation to get it.

However, never modify _ proto _. The reasons are as follows:

    • First, the most obvious reason is portability. Since not all JavaScript execution environments support this property, the code cannot be run in an environment that does not support _ proto _ after using _ proto _.
    • Secondly, it is the performance of the consideration. The current implementation of the JavaScript engine will make a lot of optimizations for the access to object properties, because these are the most commonly used. When the object's _ proto _ is modified, it is equivalent to modifying the entire inheritance structure of the object, which causes many optimizations to be no longer available.
    • Finally, the most important reason is the need to ensure the reliability of the program. Because of the change _ proto _ property, the prototype inheritance chain of an object may be completely changed. Unexpected errors occur when there are other code in the program that relies on the original inheritance chain. Typically, the prototype inheritance chain needs to remain stable.

When you need to assign a prototype object to a newly created object, you can use the Object.create method provided by ES5. For environments that do not implement ES5 standards, a object.create method that does not rely on _ proto _ can be given.

Iv. Resolve _ proto _ compatibility issues, so that the constructor is no longer dependent on the New keyword

When you use a function as a constructor, you need to make sure that the function is invoked through the new keyword.

function User (name, PasswordHash) { 
 this.name = name; 
 This.passwordhash = PasswordHash; 
} 

If you forget to use the New keyword when calling the above constructor, then:

var u = User ("Baravelli", "d8b74df393528d51cd19980ae0aa028e"); 
U Undefined 
this.name;//"Baravelli" 
this.passwordhash;//"d8b74df393528d51cd19980ae0aa028e" 

You can find that you are undefined, and this.name and This.passwordhash are assigned a value. But here's the this point is the global object.

If you declare a constructor to be dependent on the strict mode:

function User (name, PasswordHash) { 
 "use strict"; 
 this.name = name; 
 This.passwordhash = PasswordHash; 
} 
var u = User ("Baravelli", "d8b74df393528d51cd19980ae0aa028e"); 
Error:this is undefined 

When you forget to use the New keyword, a typeerror error is thrown when you invoke This.name= name. This is because in strict mode, the default point of this is set to undefined instead of the global object.

So is there a way to ensure that a function can be used as a constructor, whether or not the new keyword is invoked? The following code is an implementation that uses the instanceof action:

function User (name, PasswordHash) { 
 if (!) ( This instanceof user) {return 
  new user (name, passwordhash); 
 } 
 this.name = name; 
 This.passwordhash = PasswordHash; 
} 

var x = User ("Baravelli", "d8b74df393528d51cd19980ae0aa028e"); 
var y = new User ("Baravelli", "d8b74df393528d51cd19980ae0aa028e"); 
x instanceof User; True 
y instanceof User;//True 

The above if code block is used to handle situations where the call is not made with new. When new is not used, this point is not an instance of user, and when the new keyword is used, this point is an instance of the user type.

Another implementation that is more appropriate for use in a ES5 environment is as follows:

function user (name, passwordhash) { 
 var self = this instanceof User this:Object.create (user.prototype); 
 Self.name = name; 
 Self.passwordhash = PasswordHash; 
 return self; 
} 

The Object.create method is a ES5-provided method that accepts an object as the prototype of the newly created object. Then in a ES5 environment, you need to first implement a Object.create method:

if (typeof object.create = = "undefined") { 
 object.create = function (prototype) { 
  function C () {} 
  C.prototy PE = prototype; 
  return new C ();} 
 ; 
} 

In fact, the Object.create method also has a version that accepts the second argument, and the second parameter represents a series of attributes that are assigned on the newly created object.

When the above function does use new to invoke, it is also possible to get the new object returned correctly. This benefits from the constructor overlay mode (constructor Override pattern). The meaning of the pattern is that the return value of an expression using the New keyword can be overridden by an explicit returns. As in the above code, return self is used to explicitly define the returned value.

Of course, the above work is not necessary in some cases. However, when a function needs to be invoked as a constructor, it must be described, and using the document is a way to use the name of the function as a way of capitalizing the first letter (some of the conventions based on JavaScript language).

The above is for JavaScript prototype,getprototypeof and __proto__ in-depth study, hope to help everyone's study.

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.