How JavaScript creates an object

Keywords: Attribute Javascript Programming

We can use JavaScript's grammatical features to create objects with the idea of classes.

Method 1: Primitive method

The code is as follows:

<script>
    var obj = new Object();
    obj.name = "Kitty";//Adding attributes to objects
    obj.age = 21;
    obj.showName = function () {//Adding methods to objects
        console.log(this.name);
    };
    obj.showAge = function(){
        console.log(this.age);
    };
    obj.showName();
    obj.showAge();
</script>

this method generates an object through the new keyword, and then adds attributes and methods to construct an object according to the characteristics of JavaScript as a dynamic language. this represents the object that calls the method.

The problem with this approach is that if we need to create objects many times, we need to repeat the code many times, which is not conducive to code reuse.

Method 2: Factory method

The code is as follows:

<script>
    function createObj(){
        var obj = new Object();//create object
        obj.name = "Kitty";
        obj.age = "21";
        obj.showName = function () {
            console.log(this.name);
        };
        obj.showAge = function () {
            console.log(this.age);
        };
        return obj;
    }

    var obj1 = createObj();
    var obj2 = createObj();

    obj1.showName();
    obj1.showAge();

    obj2.showName();
    obj2.showAge();
</script>
This method also implements object creation, but similarly, if you need to create objects many times and the content of attributes is different, you need to repeat code many times. We need to reconsider the code reuse rate, and then modify the code so that it can improve the code repetition rate, and can change the factory method and pass in parameter assignment.

The improved code is as follows:

<script>
    function createObj(name,age){
        var obj = new Object();
        obj.name = name;
        obj.age = age;
        obj.showName = function () {
            console.log(this.name);
        };
        obj.showAge = function(){
            console.log(this.age);
        };

        return obj;
    }

    var obj1 = new createObj("Kitty","21");
    var obj2 = new createObj("Luo","22");

    obj1.showName();//Kitty
    obj1.showAge();//21

    obj2.showName();//luo
    obj2.showAge();//22
</script>
Although this method can improve code reuse, it has a big drawback compared with the concept of class in object-oriented. Object-oriented emphasizes that the attributes of objects are private, but the method of objects is sharing. When creating objects, the factory method above creates its own private methods for each object. At the same time, memory is wasted by creating the same logical method for each object.

The improved code is as follows:

<script>
    function createObj(name,age){
        var obj = new Object();
        obj.name = name;
        obj.age = age;
        obj.showName = showName;
        obj.showAge = showAge;
        return obj;
    }

    function showName(){
        console.log(this.name);
    }
    function showAge(){
        console.log(this.age);
    }
    
    var obj1 = new createObj("Kitty","21");
    var obj2 = new createObj("Luo","22");

    obj1.showName();//Kitty
    obj1.showAge();//21

    obj2.showName();//luo
    obj2.showAge();//22
</script>
By defining several function objects, the problem that different objects hold function objects is solved. All object methods now hold references to the above two functions. However, in this way, the functions and objects of the object are independent of each other, which is inconsistent with the idea that specific methods belong to specific classes in object-oriented.

Method 3: Constructor method

The code is as follows:

<script>
    function Person(name,age){
        this.name = name;
        this.age = age;

        this.showName = function () {
            console.log(this.name);
        };
        this.showAge = function () {
            console.log(this.age);
        };
    }
    var obj1 = new Person("Kitty","21");
    var obj2 = new Person("Luo","22");

    obj1.showName();//Kitty
    obj1.showAge();//21

    obj2.showName();//luo
    obj2.showAge();//22
</script>

Constructors, like factory methods, create unique function objects for each object. Of course, these function objects can also be defined outside the constructor, so there is the problem of the independence of objects and methods.

The biggest problem with using constructors is that every instance creates all attributes once. This is acceptable for numeric attributes, but it is unreasonable if the function method is created once for each instance.

Method 4: Prototype method

The code is as follows:

<script>
    function Person(){} //Define an empty constructor and cannot pass parameters
    //Give prototype the method of all attributes
    Person.prototype.name = "Kitty";
    Person.prototype.age = 21;
    Person.prototype.showName = function (){
        console.log(this.name);
    };
    Person.prototype.showAge = function (){
        console.log(this.age);
    };

    var obj1 = new Person("Kitty","21");
    var obj2 = new Person("Luo","22");

    obj1.showName();//Kitty
    obj1.showAge();//21

    obj2.showName();//luo
    obj2.showAge();//22
</script>
When Person objects are generated, prototype attributes are assigned to new objects. Then attributes and methods are shared. First, the problem with this method is that the constructor cannot pass parameters, and each newly generated object has a default value. Secondly, there is no problem with method sharing, but when attributes are objects with changeable states, there is a problem with attribute sharing.

The modification code is as follows:

<script>
    function Person(){} //Define an empty constructor and cannot pass parameters
    //Give prototype the method of all attributes
    Person.prototype.age = 21;
    Person.prototype.array = new Array("Kitty","luo");

    Person.prototype.showAge = function (){
        console.log(this.age);
    };
    Person.prototype.showArray = function (){
        console.log(this.array);
    };
    var obj1 = new Person();
    var obj2 = new Person();
    obj1.array.push("Wendy");//Add an element to the array attribute of obj1

    obj1.showArray();//Kitty,luo,Wendy
    obj2.showArray();//Kitty,luo,Wendy
</script>
When the above code adds elements through the array attribute of obj1, the elements of the array attribute of obj2 are also affected. The reason is that the array attribute of obj1 and obj2 objects refers to the same Array object, so changing the Array object and referring to the other Array object will naturally be affected. The mixed constructor/prototype uses the constructor definition. Object attributes, the use of prototype methods to define the object's methods, so that properties can be private, and methods can be shared.

Method 5: Mixed constructor/prototype approach

The code is as follows:

<script>
    function Person(name,age){
        this.name = name;
        this.age = age;
        this.array = new Array("Kitty","luo");
    }

    Person.prototype.showName = function (){
        console.log(this.name);
    };
    Person.prototype.showArray = function (){
        console.log(this.array);
    };
    var obj1 = new Person("Kitty",21);
    var obj2 = new Person("luo",22);
    obj1.array.push("Wendy");//Add an element to the array attribute of obj1

    obj1.showArray();//Kitty,luo,Wendy
    obj1.showName();//Kitty
    obj2.showArray();//Kitty,luo
    obj2.showName();//luo
</script>

When attributes are private, changing their attributes will not affect other objects. At the same time, methods are shared by all objects. Semantically, this meets the requirements of object-oriented programming.

Method 6: Dynamic prototyping

The code is as follows:

<script>
    function Person(name,age){
        this.name = name;
        this.age = age;
        this.array = new Array("Kitty","luo");
        //If _initialized is undefined in the Person object, it indicates that no method has been added to the Person prototype.
        if(typeof Person._initialized  == "undefined"){
            Person.prototype.showName = function () {
                console.log(this.name);
            };
            Person.prototype.showArray = function () {
                console.log(this.array);
            };
            Person._initialized = true;
        }
    }

    var obj1 = new Person("Kitty",21);
    var obj2 = new Person("luo",22);
    obj1.array.push("Wendy");//Add an element to the array attribute of obj1

    obj1.showArray();//Kitty,luo,Wendy
    obj1.showName();//Kitty
    obj2.showArray();//Kitty,luo
    obj2.showName();//luo
</script>

This approach is similar to the constructor/prototype approach. The method is added to the constructor, and an attribute is added to the constructor Person to ensure that if statement can only be executed successfully once. In practice, the most widely used constructor/prototype method is adopted. Dynamic prototyping is also popular, which is functionally equivalent to constructor/prototype methods. Don't use constructors and prototypes alone.


Posted by heckenschutze on Sat, 30 Mar 2019 16:12:28 -0700