Prototype and prototype in JavaScript

Source: Internet
Author: User

Prototype and prototype in JavaScript

What is the prototype?

The Function type has a prototype attribute, which is translated as a prototype. This attribute is a pointer pointing to an object that contains some attributes and methods that are shared by all instances (objects) generated by the current function.

Based on what we have mentioned above, we can find the following code:

function Person(){ ...}Person.prototype = { country : 'china', sayName : function(){  ... }}

First, an instance person of the Function type is created. Then, the person method prototype is an object, and the declaration points to an object. The attributes and methods in this object will be shared by the instances generated by the current person function. That is to say:

person1 = new Person();person2 = new Person();

Both person1 and person2 use the "Person" Function type instance to generate a new instance. Both of them share the common attributes of country and sayName, because they all have a pointer (_ proto _), direct to Person. the object to which prototype points. Note that the pointer _ proto _ is not standard and is defined only by browsers such as Chrome and Firefox. In reality, this attribute is not used, it is only used to understand prototype:

The usage of the prototype will be detailed later.

Object Creation Mode

Next, let's take a look at the methods and common modes for creating objects, as well as their advantages and disadvantages.

1. Factory Model

Like a factory, it abstracts the process of creating a specific object and uses functions to encapsulate the details of creating an object with a specific interface. Use a function to replace part of repetitive work. The Code is as follows:

function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){  alert(this.name); }; return o;}var person1 = createPerson("jiangshui","22","engineer");

In this way, a person is created. The factory mode solves the problem of repeated creation of multiple similar objects, but does not solve the problem of object recognition. Only an object is created. no matter whether the object is created from a human template or an animal template, the object type cannot be distinguished.

2. constructor Mode

Create a custom constructor to define attributes and methods of the custom object type.

function Person(name, age, job){ this.name = name; this.age = age; this.job = jpb; this.sayName = function(){  alert(this.name); };};var person1 = new Person(...);

3. Differences between the constructor mode and the factory mode:

  • There is no explicitly created object.
  • Assign attributes and methods to this object directly.
  • No return statement.

Person is a Function-type object. After new, an object will be generated. However, this newly generated object is assigned a value to this pointer because it is passed in a parameter in the Function, the passed content becomes the property or method of the newly generated object.

The default constructor uses uppercase letters. The code above has undergone the following steps:

  • Create a new object
  • Assign a constructor scope to a new object
  • Execute the code in the constructor
  • Returns a new object.

The generated instance contains a constructor attribute pointing to the constructor by default. For example:

alert(person1.constructor == Person);

Therefore, in the constructor mode, the instance can be identified as a specific type.

In addition, constructor is a common function. It is called with new because new objects need to be fed back. If you do not need to use this function, you can directly execute it just like a common function. For example, if you execute Person. sayName (), window. name will pop up. Because the function is executed under window, this points to window.

The constructor mode is also flawed. The methods in the constructor mode are re-created on each instance. Therefore, functions of the same name on different instances are not equal. For example:

person1.sayName == person2.sayName; //false

That is to say, the attributes and methods of each object instance generated by the constructor are unique and copied once. Attribute exclusive is necessary, because this is exactly where objects are different, but many methods and code are the same. Repeated copying is obviously a waste of resources.

So we can put the function out and point the pointer to this function in the constructor. In the generated instance, the method store is a pointer to a function, A function is shared:

function Person(name, age){ this.name = name; this.age = age; this.sayName = sayName;}function sayName(){ alert(this.name);}

But in this way, this function becomes a global function, and it is not highly correlated with the Person constructor, and there is no encapsulation.

See the prototype below.

Prototype

I have already introduced some basic prototype knowledge. Simply put, each function has a prototype attribute pointing to an object (prototype object), which can contain some attributes or methods. Then, the instance generated by this function will have an nonstandard attribute (_ proto _) pointing to the prototype.

From this point of view, you can understand that the attributes and methods produced by prototype are shared by all instances.

This solves the Sharing Problem of functions in the constructor mode above. For example, the following code:

function Person(){ ....}Person.prototype.name = "jiangshui";Person.prototype.sayName = function(){ alert(this.name);};var person1 = new Person();person1.sayName(); //jiangshui

Or

Person.prototype = { constructor : Person, name : "jiangshui", sayName : function(){  alert(this.name); }};

The second method overwrites the entire prototype Object. Therefore, you must manually specify the constructor attribute to point to the constructor. Otherwise, the constructor will point to the Object.

Sort out their relationships:

  • Person. prototype-the prototype object, which can define some attributes or parameters and is shared by all instances.
  • Person. prototype. constructor = Person-"the prototype object has a default attribute constructor pointing to the constructor to which the prototype object belongs (note that another write method will overwrite this attribute and you need to specify it again ).
  • Person1 = new Person ()-> constructor generation instance. The instance contains the constructor content and prototype object content.
  • Person1. _ proto _-point to the prototype object used to create the instance (not standard, do not use it ).

You can use isPrototypeOf () to determine the relationship between objects. For example:

Person.prototype.isPrototypeOf(person1);

When the Code reads an attribute of an object, it performs a search. Start from the current object. If no, search for the prototype object pointed to by the pointer instead of the constructor. Object instances can access but cannot override the value of the prototype object. If an attribute with the same name as the prototype object is set in the instance, the search process ends in the instance and does not access the prototype object. Therefore, the target is overwritten. Therefore, even if this attribute is set to null, it indicates that this attribute already exists in the instance and will not be canceled to access the corresponding properties of the prototype.

Therefore, you need to use the delete operator to completely delete instance attributes so that you can re-access the prototype.

The prototype is dynamic. Any modifications made to the prototype object can be immediately reflected on the instance. The reason is the loose link between the instance and the prototype. Each time you call the attribute method of the instance, a query is performed. If the prototype changes, the query result is changed.

After understanding the prototype, we can also add new methods or attributes to the native object. Native reference types such as Object, Array, and String are similar to the constructors above. We can use prototype to expand their methods. For example:

String.prototype.startsWith = function(text){ return this.indexOf(text) == 0;};var msg = "Hello World";msg.startsWith("Hello");

This code is a native reference type of String and adds a startsWith method. The function is to pass a parameter to check whether the String to be tested starts with a parameter. Because of the dynamic nature of the prototype, you only need to execute this method for all string-type variables.

However, this method is not recommended. If too many codes are used, maintenance difficulties and code confusion may occur. Generally, a native reference type is inherited and then created on the new custom type. Inheritance will be summarized later.

The prototype mode is not omnipotent. All attributes and methods in the prototype are shared by all instances. Therefore, it is very suitable for functions and other attributes that contain reference types, there will be some conflicts. For example:

function Person(){}Person.prototype = { constructor : Person, friends : ["greg","jack"]};var person1 = new Person();var person2 = new Person();person1.friends.push("tom");console.log(person2.friends);

You will see in the console that the friend of person2 has another tom, which is not what I want, but when I define a friend of person1, it does affect the instance person2.

Therefore, we need to combine the prototype mode and the constructor mode.

Constructor mode and prototype mode

This is the most common mode. constructor is used to define instance attributes and PASS Parameters to customize them. prototype is used to define methods or attributes that need to be shared by all instances. In this way, both user-defined and shared are implemented, and problems are avoided.

function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["greg","jack"];}Person.prototype = { constructor : Person, sayName : function(){  alert(this.name); }};var jiangshui = new Person("jiangshui","22","engineer");

Example

OK. Here, you may understand what the prototype is and how to create the object. But what are the usage of the prototype? Indeed, in my previous work, I had been writing some code with jQuery, and I could not use encapsulation and then generate objects to implement functions. So what exactly are these functions?

This development method is mainly used for modular and modular development. For example, you can paste and copy the Code related to the pop-up window, and modify the code to use it in the project. A better choice is to abstract and encapsulate your pop-up window function code into such a component. In this way, when you need to use a pop-up window, you only need to pass parameters to generate a pop-up window instance, you can call it.

Prototype object and prototype chain

In Javascript, all objects are objects, but objects are also different. They can be divided into two types: common objects and Function objects ).

In general, the objects generated through the new Function are Function objects, and other objects are common objects.

Example:

function f1(){  //todo}var f2 = function(){  //todo};var f3 = new Function('x','console.log(x)'); var o1 = {};var o2 = new Object();var o3 = new f1(); console.log(  typeof f1,//function  typeof f2,//function  typeof f3,//function  typeof o1,//object  typeof o2,//object  typeof o3 //object);>> function function function object object object

F1 is a function declaration, and the most common function definition method. f2 is actually an anonymous function. It assigns a value to f2, which is a function expression. f3 is not common, but it is also a function object.

Function is an object that comes with JS. When f1 and f2 are created, JS will automatically build these objects using the new Function () method. Therefore, all three objects are created through new Function.

There are two ways to create an object in Javascript: the literal volume of the object and the new expression. The creation of o1 and o2 exactly corresponds to these two methods, if you use the Java and C # ideas to understand it, o3 is the Instance Object of f1, and o3 and f1 are of the same type. At least I thought so before, but it is not...

So how can we understand it? It's easy to see if o3 is generated through the new Function. Obviously not, since it is not a Function object, it is a common object.

After a simple understanding of function objects and common objects, let's take a look at the prototype and prototype chain in Javascript:

In JS, each time a function object f1 is created, this object has some built-in attributes, including prototype and _ proto __, prototype, which is the prototype object, it records some attributes and methods of f1.

It should be noted that prototype is invisible to f1, that is, f1 does not look for the attributes and methods in prototype.

function f(){}f.prototype.foo = "abc";console.log(f.foo); //undefined

So, what is prototype used? In fact, prototype is mainly used for inheritance. Generally speaking, the attributes and methods defined in prototype are reserved for their "descendants". Therefore, subclass can access the attributes and methods in prototype.

To know how f1 left prototype to "future generations", we need to know about the prototype chain in JS. At this time, _ proto _ in JS entered the market. This guy is very strange, it is so hidden that you often cannot see it, but it exists in both common objects and function objects. Its function is to save prototype objects of the parent class, when JS creates an object through the new expression, it usually assigns the prototype of the parent class to the _ proto _ attribute of the new object, which forms a generation-to-generation inheritance...

function f(){}f.prototype.foo = "abc";var obj = new f();console.log(obj.foo); //abc

Now we know that _ proto _ in obj stores the prototype of f. What is saved in _ proto _ in prototype of f? See:

, F. the prototype _ proto _ stores the Object. prototype, Object. prototype objects also contain _ proto __, and the output result shows that the Object. prototype. _ proto _ is null, indicating the end Of the obj object prototype chain. As shown in:

After the obj object has such a prototype chain, when obj. when foo is executed, obj first searches for its own prototype, but does not find its own prototype. When foo is not found, obj searches for it along the prototype chain...

In the above example, we define the foo attribute on prototype of f. Then obj will find this attribute on the prototype chain and execute it.

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.