You don't know Javascript--item13 understand prototype, getprototypeof and __proto__

Source: Internet
Author: User

1, in-depth understanding of prototype, getprototypeof and _ proto _

Prototype,getpropertyof and _ proto _ are three ways to access prototype. They are named in much the same way that it is easy to confuse.

They are used in the following ways:

    • c.prototype: A generic object that is used to establish its prototype for a type. For example, C.prototype = xxx, so that the object using new C () will be the prototype object of XXX. Of course, you can also get the prototype object of obj using Obj.prototype.

    • 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 nonstandard method used to get the prototype object of the Obj object.

To fully understand the various ways to get a prototype, here is an example:

 function User(name, PasswordHash) {       This. name = name; This. PasswordHash = PasswordHash; } User.prototype.toString = function() {      return the [User]+ This. Name +"]";  }; User.prototype.checkPassword = function(password) {      returnhash (password) = = = This. PasswordHash; };varU =NewUser ("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 were added to the prototype object, namely ToString and Checkpassword. When you call the user constructor to get a new object U, its prototype object is automatically assigned to the User.prototype object. that is u.prototype = = = User.prototype will return true.

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

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

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

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

ObjectUser//true  

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

u.__ proto __User//true  

So in JavaScript, the concept of a class is done together by the constructor (User) and the prototype object (User.prototype), which 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 properties common to all objects, such as the Checkpassword and ToString methods in the example above. As the following picture shows:

2, get the object first use object.getprototypeof instead of _ proto _

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

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

// 在某些环境中  empty = Object.create(null); // object with no prototype  "_proto _"inempty; // false (in some environments)  // 在某些环境中  empty = Object.create(null); // object with no prototype  "_proto_"inempty; // true (in some environments)  

So when the Object.getprototypeof method is supported in the environment, it is preferred. Even if it is not supported, you can implement one in order to:

if  ( typeof  object . getprototypeof = =  "undefined" ) {object . getprototypeof = function   { var t = typeof  obj; if  (!obj | | (t!==  "object"  && t!==  "function" )) {throw  new  T          Ypeerror  ( "not an object" );      } return  obj._proto_;  }; }  

The code above first checks the current environment, and if object.getprototypeof is already supported, it will no longer be defined.

3, never to modify _ proto _

In contrast to object.getprototypeof,_ proto _ 's special is also reflected in its ability to modify an object's prototype inheritance chain. Because it is a property, it can be set in addition to the operation that gets 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, after using _ proto _ , the code cannot run in an environment that does not support _ proto _ .

    • Secondly, it is a performance consideration. The implementation of the JavaScript engine now has a lot of optimizations for the access to object properties, because these operations are most commonly used. When the _ proto _ of an object is modified, it is equivalent to modifying the entire inheritance structure of an 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 the object's prototype inheritance chain may be completely changed after the Proto _ property is changed. Unexpected errors occur when other code in the program relies on the original inheritance chain. In general, 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 the ES5 standard, an implementation of the Object.create method that does not depend on _ proto _ can be given.

4, Solve _ proto _ compatibility problem, let the constructor no longer rely on the new keyword

When using function as a constructor, you need to make sure that the function is called with 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");  // undefined  this// "baravelli"  this// "d8b74df393528d51cd19980ae0aa028e"  

It can be found that the resulting u is undefined, while THIS.name and This.passwordhash are assigned values. But here the this point is the global object.

If the constructor is declared to be dependent on strict mode:

function User(name, passwordHash) {      "use strict";      this.name = name;      this.passwordHash = passwordHash;  }  var u = User("baravelli""d8b74df393528d51cd19980ae0aa028e");  // error: this is undefined  

Then when you forget to use the New keyword, you will throw a typeerror error when calling 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 treated as a constructor, regardless of whether the new keyword is used or not? The following code is an implementation that uses the instanceof operation:

 function User(name, PasswordHash) {      if(! ( This instanceofUser)) {return NewUser (name, PasswordHash); } This. name = name; This. PasswordHash = PasswordHash; }varx = User ("Baravelli","d8b74df393528d51cd19980ae0aa028e");vary =NewUser ("Baravelli","d8b74df393528d51cd19980ae0aa028e"); XinstanceofUser;//TrueYinstanceofUser;//True

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

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

function User(name, passwordHash) {      varselfinstanceof User ? this : Object.create(User.prototype);      self.name = name;      self.passwordHash = passwordHash;      returnself;  }  

The Object.create method is a method provided by ES5 that can accept an object as a prototype of the newly created object. In a non-ES5 environment, it is necessary to implement a Object.create method first:

if (typeofObject"undefined") {      Objectfunction(prototype) {          function C() { }          C.prototype = prototype;          returnnew 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 given on the newly created object.

When the above function does use new for invocation, it is also possible to get the new object returned correctly. This is due to the constructor overlay mode (Constructor override pattern). The implication of this pattern is that the return value of an expression that uses the New keyword can be overridden by an explicit return. As in the preceding 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 called as a constructor, it must be described, and using a document is a way to capitalize the name of a function in the same way (based on some conventional JavaScript language).

This article refers to: effective JavaScript reading notes

Copyright NOTICE: This article is the original article, reproduced please specify: http://blog.csdn.net/i10630226

You don't know Javascript--item13 understand prototype, getprototypeof and __proto__

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.