Some methods for defining classes and objects in JavaScript

Source: Internet
Author: User

Recently, I encountered a friend asking me "hoisting. That is to say, the declaration of all variables in js is set to the top, and the value assignment occurs later. Let's take a look at this example:

var a = 'global';(function () {alert(a);var a = 'local';})();

At first glance, what is the output result of this example? 'Global '? Or 'local '? In fact, none of them. The output is undefined, so don't be confused. I just want to talk about it.

In fact, it is very simple. You will understand the JavaScript operating mechanism. We can regard this phenomenon as "pre-declaration ". However, if you have a deep understanding, you will understand it more thoroughly.

This actually involves the object property binding mechanism. Because all JavaScript Functions are an object. The variables declared in the function can be seen as "similar attributes" of this object ". The binding of object attributes can be divided into "Early binding" and "late binding.

Early binding refers to defining its attributes and methods before instantiating an object. The parsing program can be converted into machine code in advance. Generally, strong-type languages such as C ++ and java are pre-bound. JavaScript is not a strongly typed language. It uses the "late binding" mechanism.

Late binding means that you do not need to check the object type before running the program. You only need to check whether the object supports features and methods. You can perform a large number of operations on the object before binding without any penalty.

The "pre-declaration" Phenomenon in the above Code can be explained by the "late binding" mechanism. In the function scope, all variables are "late binding. That is, the Declaration is top-level. So the above Code is consistent with the following:

    var a = 'global';    (function () {        var a;        alert(a);        a = 'local';    })();

Before alert (a), only a is declared and no value is assigned. The results can be imagined.

In JavaScript, I know several ways to define classes and objects:

Direct Volume Method

Directly constructing objects using a volume is the most basic method, but there are also many drawbacks.

var Obj = new Object;Obj.name = 'sun';Obj.showName = function() {    alert('this.name');}

We constructed an object Obj, which has a property name and a method showName. But what if we want to build another similar object? Do I have to repeat it again? NO !, We can use a factory function that returns a specific type of object. Like a factory, the pipeline outputs the specific type of results we want.

Factory method
function createObj(name) {    var tempObj = new Object;    tempObj.name = name;    tempObj.showName = function () {        alert(this.name);    };    return tempObj;}var obj1 = createObj('obj_one');var obj2 = createObj('obj_two');

Many people do not regard this factory function as a form of building objects. One part of the reason is semantics: that is, it is not as formal as it is constructed using the new operator. Another bigger reason is that the factory creates a new showName () function every time it produces an object, that is, each object has a different version, but they actually share the same function.

Some people define showName outside the factory function and point it to this method through the property to avoid this problem:

function showName () {    alert(this.name);}    function createObj(name) {    var tempObj = new Object;    tempObj.name = name;    tempObj.showName = showName;    return tempObj;}var obj1 = createObj('obj_one');var obj2 = createObj('obj_two');

Unfortunately, this method makes the showName () function look different from an object method.

Constructor Method

This method is used to solve the first problem of the factory function above, that is, the problem of no new operator. However, the second problem still cannot be solved. Let's take a look.

function Obj(name) {    this.name = name;    this.showName = function () {        alert(this.name);    }}var obj1 = new Obj('obj_one');var obj2 = new Obj('obj_two');

It does not need to create an object in the constructor, because an object is automatically created when the new operator is executed and can be accessed only through this. Therefore, we can assign values to this object directly through this. And no need to return, because this points to the return value of the constructor by default. At the same time, the new keyword is used to create the desired object. Does it feel more "formal. Unfortunately, it still cannot solve the problem of repeatedly generating method functions, which is the same as that of factory functions.

Prototype

Compared with the above method, this method has a great advantage, that is, it solves the problem that method functions will be generated multiple times. It uses the prototype attribute of the object. The dependency prototype can override the object instance.

var Obj = function () {}Obj.prototype.name = 'me';Obj.prototype.showName = function () {    alert(this.name);}var obj1 = new Obj();var obj2 = new Obj();

We rely on the prototype to override the constructor. Both attributes and methods are referenced by the prototype to create new objects. Therefore, they are created only once. Unfortunately, this method has two fatal problems:

  1. You cannot write the desired attribute when building an object. Because the prototype is outside the scope of the constructor, you cannot write the attribute value when creating an object by passing parameters. The value can only be overwritten after the object is created.
  2. The fatal problem is that when the property points to an object, this object will be shared by multiple instances. Consider the following code:
var Obj = function () {}Obj.prototype.name = 'me';Obj.prototype.flag = new Array('A', 'B');Obj.prototype.showName = function () {    alert(this.name);}var obj1 = new Obj();var obj2 = new Obj();obj1.flag.push('C');alert(obj1.flag); // A,B,Calert(obj2.flag); //A,B,C

Yes, when the flag property points to the object, the instance obj1 and obj2 share it, even if we only changed the flag property of obj1, but its change is visible in the instance obj2. In the face of this problem, we have to think about whether to combine the [constructor method] with the [prototype method] so that they can complement each other...

Constructor and prototype

Let's create the attribute using the constructor method, and create it using the prototype method:

var Obj = function (name) {    this.name = name;    this.flag = new Array('A', 'B');}Obj.prototype = {    showName : function () {        alert(this.name);    }}var obj1 = new Obj();var obj2 = new Obj();obj1.flag.push('C');alert(obj1.flag); // A,B,Calert(obj2.flag); //A,B

This method effectively combines the advantages of the prototype and constructor, which is currently the most used and the least side effects.

However, some people who want to pursue perfection are not satisfied, because they have not met their requirements visually, the process of creating a method through a prototype still visually makes people think that it is not like an instance method (especially for developers of traditional OOP languages .) Therefore, we can make the prototype activity and add it to the constructor so that the constructor can be visually unified. This series of processes can be completed with only one judgment.

var Obj = function (name) {    this.name = name;    this.flag = new Array('A', 'B');    if (typeof Obj._init == 'undefined') {        Obj.prototype = {            showName : function () {                alert(this.name);            }        };        Obj._init = true;    }}

As shown above, use _ init as a flag to determine whether a method has been created for the prototype. If yes, it will not be executed. In fact, there is no change in nature, and the method is still created through the prototype. The only difference is that this constructor looks "unified.

However, there is a problem with this dynamic prototype method, which is not discussed in JavaScript advanced programming. When you create the first object, prototype is inaccessible because it was not created before the object is instantiated. Therefore, the first object cannot access the prototype method. This method also has problems in subclass inheritance.

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.