Functions, this, and prototype in Javascript

Source: Internet
Author: User

About Functions

In JavaScript, a function is actually an object and has the characteristics of the reference type. Therefore, you can directly pass the function to a variable, which indicates a pointer to the function "object", for example:

function test(message){          alert(message);     }     var f = test;     f('hello world');
You can also directly assign the function declaration to the variable:
var f = function(message){          alert(message);          };     f('hello world');

In this case, the function name can be omitted in the function declaration, because the name has no meaning at this time, we can directly call the function through the variable F.

Through the function type, we can better understand the function as an object:

var f = new Function("message","alert(message);");     f('hello world');

About this

This can be seen as the actual scope context of the called function. Compare the execution results of the following functions:

Function Test () {This. property = 'Hello world';} test (); alert (window. property); // because it is called globally, this in the test function actually points to the Global Object (window) var OBJ ={}; test. call (OBJ); // specify the execution context range through the first parameter of call. Therefore, this points to the OBJ instance in the test function. Alert (obj. property); var obj2 ={}; obj2.test2 = test; // point the obj2 instance method test to the global test method obj2.test2 (); // because the test method is called on obj2, therefore, this in the test function also points to the obj2 instance alert (obj2.property );

Define type

Constructor can be defined in Javascript. constructor is no different from general functions. If we use the New Keyword when creating an instance, this function has the constructor feature, otherwise, it is a general function. As shown below, we define a person type:

function Person(){     this.name = 'xfrog';     this.Say = function(){          alert(this.name);     };}

When the new keyword is used, you can create a new person object instance:

var p1 = new Person();p1.Say();

If the new keyword is not used, the person function will be executed directly. Because the execution context is a global range, the name attribute and the say method will be added to the window object:

Person();Say();window.Say();

Prototype

Note the above person definition method. When you use new to create a person instance, the person constructor will be executed, that is, the name attribute and the say method will be declared, which may cause efficiency problems, note the following code:

var p1 = new Person();     var p2 = new Person();     var test = p1.Say == p2.Say;

Compare the say function pointers P1 and P2, and return false, indicating that the say method in each person instance is independent. In fact, the say function has the same functions, there is no need to re-allocate the say function "object" for each object. If there are many person instances, a large amount of memory will be consumed.

If you extract the say function into the global execution range, it seems that the following problem can be solved:

function Person(){          this.name = 'xfrog';          this.Say = say;          }     function say(){          alert(this.name);          }     var p1 = new Person();     var p2 = new Person();     alert(p1.Say == p2.Say);     p1.name = 'wang';     p1.Say();

Because this is always related to the execution context, the "say" method in P1 and P2 instances correctly returns the name attribute of the corresponding instance. However, using this method violates the object-oriented idea and also loses the type seal principle. It also produces a large number of global functions.

To solve these disadvantages, JavaScript introduces the concept of prototype. A prototype can be viewed as a Type sharing zone, and the prototype itself is an object, the attributes in the object are shared for the type. Each type in Javascript uses the prototype attribute to represent the prototype. You can use this attribute to specify the sharing method:

 

Function person () {} person. prototype. name = 'xfrog'; person. prototype. say = function () {alert (this. name) ;}; var p1 = new person (); var P2 = new person (); alert (p1.say = p2.say); // return true

Why can I access the say method through p1.say? This is because the ecmascript Standard specifies the search sequence of the type attribute: first, search for the Type instance. If not, continue to search for the Type prototype. This search path adopts the short circuit algorithm, return after finding the first one. Consider the following code:

Function person () {This. name = 'wang';} person. prototype. name = 'xfrog'; person. prototype. say = function () {alert (this. name);} var p1 = new person (); p1.say (); // Wang will be returned

 

The prototype mentioned above is actually an object. Can we directly access it? Some browser implementations (such as chrome and fixfox) can indeed access internal prototype objects through the _ PROTO _ attribute of the instance, this feature indicates that the JavaScript engine saves prototype references to each object through a variable. This ensures that prototype is shared for instances of the entire type. For example, you can access the say method in chrome as follows:

p1.__proto__["Say"]();

Since the prototype is an object, we can directly assign an object to prototype:

function Person(){     }     Person.prototype = {name:'xfrog', Say:function(){          alert(this.name);     }};

Note that in this method, the prototype of person is replaced completely. prototype. the name method is slightly different. This is because any type of prototype is added to the JavaScript engine. The prototype contains a reference to the constructor, therefore, when replacing prototype, We need to manually add the constructor attribute:

Person.prototype = {           constructor: Person,          name :'xfrog',          Say:function(){               alert(this.name);          }     }

Note: Because prototype is shared for the entire type, the reference type in prototype may be faulty. The previous say function is used as an object and is also a reference type, therefore, the say in each instance points to the same function in the prototype object. This is no problem in itself and is also the original intention of using the prototype. However, for other referenced objects, the result may not be what we want:

function Person(){     }     Person.prototype = {          name: 'xfrog',          obj : { age: 18 },          Say : function(){               alert(this.obj.age);          }     };     var p1 = new Person();     var p2 = new Person();     p1.obj.age = 20;     p1.Say();     p2.Say();

P2.say returns 20 because the OBJ attribute is shared as the prototype attribute and only one instance exists in the memory. Therefore, after P1 is modified, P2 can only get the modified status. To avoid this situation, you can put the OBJ attribute in the instance:

function Person(){          this.obj = { age: 18 };     }
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.