A summary of several ways to define JavaScript classes

Source: Internet
Author: User
Tags class definition constructor json mixed static class

When we talk about object orientation, we can think of classes, objects, encapsulation, inheritance, and polymorphism. The book "JavaScript Advanced Programming" (translated by People's Posts and Telecommunications Press, Cao Li and Zhang Xin. The English name is: Professional JavaScript for Web Developers) is quite detailed. Let's look at the various methods of defining classes in JavaScript.
1. Factory approach

    To create your own classes and objects in javaScript, we should master it. We all know that the properties of objects in javaScript can be dynamically defined after the object is created, such as the following code:

<script type = "text / javascript">
    //definition
    var oCar = new Object ();
    oCar.color = "red";
    oCar.doors = 4;
    oCar.showColor = function () {
        alert (this.color);
    }
    //transfer
    oCar.showColor ();
</ script>

    We can easily use oCar objects, but we want to create multiple Car instances. We can use a function to encapsulate the above code to achieve: <script type = "text / javascript">
    //definition
    function createCar () {
        var oCar = new Object ();
        oCar.color = "red";
        oCar.doors = 4;
        oCar.showColor = function () {
            alert (this.color);
        }
        return oCar;
    }
    //transfer
    var ocar1 = createCar ();
    var ocar2 = createCar ();
    ocar1.color = "black";
    ocar1.showColor ();
    ocar2.showColor ();
</ script>

    By the way, the default member properties of javaScript objects are all public. This method is called the factory method, and we create a factory that can create and return a specific type of object.

    This is a bit interesting, but the methods we often use to create objects in object orientation are:

Car car = new Car ();

    The use of the new keyword is already well-received, so we use the above method to always feel awkward in defining it, and to create new properties and functions each time it is called, it is not practical in function. Let's take a look at the class definition form of the constructor.

2. Constructor

This approach looks a bit like a factory function. The specific performance is as follows:

<script type = "text / javascript">
    //definition
    function Car (color, doors) {
        this.color = color;
        this.doors = doors;
        this.showColor = function () {
            alert (this.color);
        };
    }
    //transfer
    var car1 = new Car ("red", 4);
    var car2 = new Car ("blue", 4);
    car1.showColor ();
    car2.showColor ();
</ script>

    It looks like the effect is obvious. I feel a bit interesting. Creating objects inside the constructor uses the this keyword, and creating objects using the new operator feels very kind. But it is also a bit problematic: every time a new object is created, all properties are created, including the creation of functions, which means that multiple objects are completely independent. The purpose of our class definition is to share methods and data, but the car1 object and the car2 object are both Independent properties and functions, at least we should share methods. This is the advantage of the prototype method.

3. Prototyping

Using the prototype property of an object, you can see the prototype on which the new object is created. Methods as below:

<script type = "text / javascript">
    //definition
    function Car () {
    };
    Car.prototype.color = "red";
    Car.prototype.doors = 4;
    Car.prototype.drivers = new Array ("Tom", "Jerry");
    Car.prototype.showColor = function () {
        alert (this.color);
    }
    //transfer:
    var car1 = new Car ();
    var car2 = new Car ();
    car1.showColor ();
    car2.showColor ();
    alert (car1.drivers);
    car1.drivers.push ("stephen");
    alert (car1.drivers); // Result: Tom, Jerry, stephen
    alert (car2.drivers); // Result: Tom, Jerry, stephen

 

// You can use json to simplify the definition of prototype:

        Car.prototype =
        {
            color: "red",
            doors: 4,
            drivers: ["Tom", "Jerry", 'safdad'],
            showColor: function () {
                alert (this.color);
            }
        } </ script>

 

    First of all, the constructor of this code, there is no code in it, and then the properties of the Car object are defined by adding properties to the prototype property of the object. This method is good, but the problem is that Car's object points to an Array pointer. Both Car objects point to the same Array. When one object car1 changes the reference of the attribute object (array Array), the other object car2 also At the same time, this is not allowed.

    At the same time, the problem is also manifested in that the prototype cannot take any initialization parameters, which causes the constructor to fail to initialize properly. This needs to be solved in another way: that is the mixed constructor / prototype pattern.

4. Mixed constructor / prototype pattern

Using a combination of constructor and prototype methods, it is very convenient to define classes.

<script type = "text / javascript">
//definition
    function Car (color, doors)
   {
        this.color = color;
        this.doors = doors;
        this.drivers = new Array ("Tom", "Jerry");
   }

   Car.prototype.showColor = function () {
        alert (this.color);
   }
  
   //transfer:
   var car1 = new Car ('red', 4);
   var car2 = new Car ('blue', 4);
  
   car1.showColor ();
   car2.showColor ();
  
   alert (car1.drivers);
   car1.drivers.push ("stephen");
   alert (car1.drivers); // Result: Tom, Jerry, stephen
   alert (car2.drivers); // Result: Tom, Jerry
   alert (car1 instanceof Car);

</ script>

 

    This method is to define attributes internally, and put methods outside to define them using prototypes. Solved the problem of the third method.

    This method should actually be very friendly, but compared to the syntax of java, there should be some disharmony and feel more messy. For C ++, we don't feel so troublesome, but the developers of C ++ are generally JavaScript is rarely involved in this case, and for J2EE developers, there is always something awkward about this approach. I always feel that it is not friendly packaging. In fact, it is just that the visual packaging effect is not very good. If you want to achieve the visual packaging effect and achieve the effect of this method, you can do it. I think it is actually more troublesome. That's dynamic prototyping.

5. Dynamic Prototype

For developers accustomed to using other languages, using a mixed constructor / prototype approach doesn't feel so harmonious. After all, when defining classes, most object-oriented languages have a visual encapsulation of properties and methods. Consider the following C # class:

class Car // class
{
    public string color = "red";
    public int doors = 4;
    public int mpg = 23;

    public Car (string color, int doors, int mpg) // constructor
    {
        this.color = color;
        this.doors = doors;
        this.mpg = mpg;
    }
    public void showColor () // method
    {
        Console.WriteLine (this.color);
    }
}

C # nicely packs all the properties and methods of the Car class, so when you see this code, you know what function it needs to implement, and it defines information about an object. Critics of the mixed constructor / prototype approach find it illogical to find properties in the constructor and find methods outside of them. Therefore, they designed a dynamic prototyping method to provide a friendlier coding style.

The basic idea of the dynamic prototype method is the same as the hybrid constructor / prototype approach, that is, defining non-function attributes within the constructor, while function attributes are defined using prototype attributes. The only difference is the location of the method assigned to the object. Here is the Car class rewritten with the dynamic prototype method:

    <script type = "text / javascript">
        //definition
        function Car () {
            this.color = "red";
            this.doors = 4;
            this.drivers = new Array ("Tom", "Jerry");
            if (typeof Car._initialized == "undefined") {
                Car.prototype.showColor = function () {
                    alert (this.color);
                }
                // ............
            }
            // finally defined
            Car._initialized = true;
        }
    </ script>

This constructor does not change until it checks whether typeof Car._initialized is equal to "undefined". This line of code is the most important part of the dynamic prototype method. If this value is undefined, the constructor will continue to define the object's methods in prototype mode, and then set Car._initialized to true. If this value is defined (when its value is true, the value of typeof is Boolean), then the method is no longer created. simple 

In other words, this method uses the flag (_initialized) to determine if any methods have been assigned to the prototype. This method is only created and assigned once. To please traditional OOP developers, this code looks more like a class definition in other languages.

6 Hybrid plant approach


This method is usually a workaround when the former method cannot be applied. Its purpose is to create a fake constructor that only returns a new instance of another object. This code looks very similar to the factory function:

function Car () {
            var oTempCar = new Object ();
            oTempCar.color = "red";
            oTempCar.doors = 4;
            oTempCar.mpg = 23;
            oTempCar.showColor = function () {
                alert (this.color);
            }
            return oTempCar;
        }

Unlike the classic approach, this approach uses the new operator to make it look like a real constructor:
var oCar = new Car ();

 

Since the new operator is called inside the Car () constructor, the second new operator (outside the constructor) is ignored. The object created inside the constructor is passed back to the variable var. This approach has the same problems as the classic approach in terms of the internal management of the object method. It is strongly recommended to avoid this method unless absolutely necessary (see Chapter 15).
Summary: (in which way)
The most widely used currently is the hybrid constructor / prototype approach. In addition, dynamic prototyping methods are also popular and are functionally equivalent to the constructor / prototype approach. Either way can be used. But don't use the classic constructor or prototype method alone, because it will introduce problems to the code.
// ps
// static class (1: function)
    var CarCollection = new function () {
        var _carCollection = new Array (); // global, private
        this.Add = function (objCar) {
            alert ('Add');
        }
        this.Get = function (carid) {
            alert ('Get');
        }
    }

// static class (2: json)

    var Car = {
        color: 'red',
        doors: 4,
        showColor: function () {alert (this.color);}
    }
    Car.showColor ();


 

Trackback:

http://blog.csdn.net/avon520/article/details/3819751

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.