Learn the prototype, getPrototypeOf and _ proto ___ javascript skills of javascript.

Source: Internet
Author: User
I want to learn about prototype, getPrototypeOf, and _ proto __of javascript. I have learned three methods for accessing prototype. If you are interested, refer to section 1. Understanding prototype in depth, getPrototypeOf and _ proto _

Prototype, getPropertyOf, and _ proto _ are three methods used to access prototype. Their naming methods are similar, so they are easy to confuse.

They are used as follows:

  • C. prototype: It is generally used to create a prototype for a type to inherit objects. For example, C. prototype = xxx, so that the prototype of the object obtained using new C () is xxx. Of course, you can use obj. prototype to obtain the prototype object of obj.
  • GetPropertyOf: Object. getPropertyOf (obj) is a standard method used in es5.
  • _ Proto _: obj. _ proto _ is a non-standard method used to obtain the prototype object of the obj object.

To fully understand the methods for obtaining a prototype, the following is 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 attribute. The value of this attribute is an empty object. In the preceding example, two methods are added to the prototype object, toString and checkPassword. When the User constructor is called to obtain a new object u, its prototype object is automatically assigned to the User. prototype object. That is, u. prototype = User. prototype returns true.

User Function, User. prototype, the relationship between object u can be expressed as follows:

The arrow in represents the inheritance relationship. When you access certain properties of the u object, you will first try to read the properties of the u object. If the u object does not have this property, you will find its prototype object.

For example, when you call u. when checkPassword () is used, because checkPassword is defined on its prototype object, this attribute cannot be found on the u object, and the search order is u-> u. prototype (User. prototype ).

As mentioned above, the getPrototypeOf method is the standard method in es5. Therefore:

Object.getPrototypeOf(u) === User.prototype; // true 

In some environments, a non-standard _ proto _ attribute is provided to obtain the prototype object of an object. When the environment does not provide the ES5 standard method getPrototypeOf, You can temporarily use this attribute as an alternative. You can use the following code to test whether _ proto _ is supported in the environment _:

u.__ proto __ === User.prototype; // true 

So in JavaScript,The concept of a class is jointly implemented by the constructor (User) and the prototype used for sharing methods between instances (User. prototype.The constructor is responsible for constructing attributes unique to each object, such as the name and password attributes in the preceding example. The prototype object stores the attributes shared by all objects, such as the checkPassword and toString methods in the preceding example. As shown in the following figure:

2. Get objects first use Object. getPrototypeOf instead of _ proto _

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

Because not all environments provide the _ proto _ attribute, and the implementation methods of each environment are different, some results may be inconsistent, for example, for objects with a null prototype:

// Var empty = Object in some environments. create (null); // object with no prototype "_ proto _" in empty; // false (in some environments) // var empty = Object in some environments. 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 preferred. Even if not, 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 an object");   }   return obj._proto_;  }; } 

The above code first checks the current environment. If Object. getPrototypeOf is already supported, the definition will not be repeated.

3. Never modify _ proto _

Compared with Object. getPrototypeOf, the special feature of _ proto _ is that it can modify the prototype inheritance chain of an Object. Because it is an attribute, in addition to the operation to obtain it, it can also be set.

However, do not modify _ proto _. The reason is as follows:

  • First, the most obvious reason is portability. Because not all JavaScript Execution environments support this attribute, after _ proto _ is used, the Code cannot run in those environments that do not support _ proto.
  • Second, performance considerations. The implementation of the JavaScript engine will greatly optimize the access to object attributes, because these operations are the most common. After the _ proto _ of the object is modified, it is equivalent to modifying the entire inheritance structure of the object. In this way, many optimizations are no longer available.
  • Finally, the most important reason is to ensure program reliability. Because after the _ proto _ attribute is changed, the prototype inheritance chain of the object may be completely changed. When other code in the program depends on the original inheritance chain, unexpected errors will occur. Generally, the prototype inheritance chain must be stable.

When you need to assign a prototype Object to a new Object, you can use the Object. create method provided by ES5. For environments that do not implement the ES5 standard, an Object. create method independent of _ proto _ can be provided.

4. Solve the _ proto _ compatibility problem so that the constructor no longer depends on the new Keyword

When using a function as a constructor, make sure that the function is called using 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" 

We can find that u is undefined, and this. name and this. passwordHash are assigned a value. However, this points to a global object.

If you declare the 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 

If you forget to use the new keyword, A TypeError is thrown when you call this. name = name. This is because in strict mode, the default direction of this will be set to undefined rather than global objects.

Is there a way to ensure that a function can be used as a constructor no matter whether the new keyword is used or not when a function is called? The following code is an implementation method that uses the instanceof operation:

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 the situation where new is not used for calling. When new is not used, this is not a User instance. When the new keyword is used, this is a User-type instance.

Another method that is more suitable for ES5 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 provided by es5. it can accept an Object as the prototype of the newly created Object. In a non-ES5 environment, you must first implement an Object. create method:

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

In fact, the Object. create method also has a version that accepts the second parameter. The second parameter represents a series of attributes assigned to the newly created Object.

When the preceding function is called with new, the new object is returned correctly. This benefits from Constructor Override Pattern ). This mode means that the return value of an expression with the new Keyword can be overwritten by an explicit return. As the above Code uses return self to explicitly define the return value.

Of course, the above work is not necessary in some situations. However, when a function needs to be called as a constructor, it must be described. Document is a method, it is also a way to name a function using uppercase letters (based on some conventions in the JavaScript language ).

The above is an in-depth study of javascript prototype, getPrototypeOf, and _ proto _, hoping to help you with your learning.

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.