Eight Ways to Create Objects in JavaScript

Keywords: Attribute Javascript

Eight Ways to Create Objects in JavaScript

1. Form of literal quantity

var obj = {};         // Declared object
obj.name = "Lau Andy";  // Adding attributes to objects
obj.age = 55;

2. Constructor

var obj = new Object(); //Create objects using constructors
obj.name = "Lau Andy";    // Adding attributes to objects
obj.age = 55;

Using Object constructors and object literals to create a single object, using the same interface, will produce a lot of repetitive code.

3. Factory Model

Functions are used to encapsulate a class of objects, and specific interfaces (passing parameters) are used to create object details.

function creatPerson(name,age){
    var obj = new Object();      //Create an empty object
    obj.name = name;             //Adding attributes and methods to empty objects created
    obj.age = age;
    obj.sayName = function(){
        alert(this.name);
    }
    return obj;                  //Returns the object created in the factory function
}
var person1 = creatPerson("Alex",25);
console.log(person1.name);        //Alex
var person2 = creatPerson("Oliver",18);
console.log(person2.age);         //18

4. Constructor pattern

Custom constructors can be created to define properties and methods of custom objects.

function Person(name,age){     //The constructor function name begins with a capital letter
    this.name = name;          
    this.age = age;
    this.sayName = function(){
        console.log(this.name);
    }
}
var person1 = new Person("Alex",25);  //The new keyword creates an object instance that this points to. 
console.log(person1.name);            //Alex
var person2 = new Person("Oliver",18);
console.log(person2.name);          //Oliver

"Constructor", in fact, is a common function, but the internal use of this variable. By using the new keyword for the constructor, an instance can be generated, and this variable is bound to the instance object.

To create a new instance of Person, you must use the new keyword. This method actually calls the constructor through the following processes:
(1) Create an empty object;
(2) The empty object points to the prototype link (so this points to the empty object);
(3) Execute the code in the constructor (add attributes to the empty object);
(4) Since the constructor person does not return a return value, the empty object is returned and assigned to the new object person1. (Without retuen, the default is return this; if the constructor person has return, it simply gives the result of return to the new object).

The process of instantiation is actually the process of copying constructor attributes and methods.

All objects created by the constructor pattern inherit from Object. So all the objects created in this example are both instances of Object and Person.

alert(person1 instanceof Object);  //true 
alert(person1 instanceof Person);  //true 
alert(person2 instanceof Object);  //true 
alert(person2 instanceof Person);  //true

The main problem with using constructors is that each method is recreated on each instance.

In the next prototype pattern, the shared methods are placed in the prototype, so no matter how many instances are created, these methods will not be created with the creation of instances, saving memory. When these methods are invoked, they are first searched from the instance. If they are not found in the instance, they are searched from the prototype.

If these methods are written in the constructor, when instantiated, all the attributes and methods in the constructor will be copied, then each instance will have these methods, which wastes memory.

//Both person1 and person2 have a method called sayName(). These two methods are not instances of the same Function. The scope chains of two sayName() functions are different.
alert(person1.sayName === person2.sayName);  //false  

Of course, you can also move the function definition out of the constructor. The person1 and person2 objects share the same sayName() function defined in the global scope.

function Person(name, age){ 
    this.name = name; 
    this.age = age; 
    this.sayName = sayName;    //Using sayName Method in Constructor
} 
 //Define the sayName() method in global scope.
function sayName(){ 
    alert(this.name); 
} 
var person1 = new Person("Alex",25);
var person2 = new Person("Oliver", 18); 
alert(person1.sayName === person2.sayName);  //true 
But doing so pollutes the global scope.

5. Prototype Model

Prototype is the prototype object of the instance created by calling the constructor.
Using prototype objects, all object instances can share the attributes and methods it contains. The invariant attributes and methods can be defined directly on the prototype object.

function Person(){};             //The constructor is an empty function
//Add the sayName() method and all attributes directly to the prototype.
Person.prototype.name = "Alex";
Person.prototype.age = 25;
Person.prototype.sayName = function(){
    console.log(this.name);
};  
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);  //Alex
console.log(person2.name);  //Alex

The instance object created does not contain any attributes and methods. You can still call person1.sayName(). It is realized by the process of finding object attributes. The internal attributes of the instance object [[Prototype]] point to the prototype object of the function, and the prototype object contains the sayName() method.

When the code reads an attribute of an object, it performs a search, aiming at an attribute with a given name. Search begins with the object instance itself. If an attribute with a given name is found in the instance, the value of the attribute is returned; if not, the prototype object pointed by the pointer is continued to be searched for an attribute with a given name in the prototype object. If this property is found in the prototype object, the value of the property is returned.

Concise version prototype mode

Rewrite the entire prototype object with an object literal containing all attributes and methods.

function Person(){};
Person.prototype = {
    name: "Alex",
    age: 25,
    sayName: function(){
        console.log(this.name);
    }
};
var person1 = new Person();  
console.log(person1.name);

In this way, the prototype object is completely rewritten, and the constructor attribute no longer points to Person, but to Object.

var friend = new Person();
alert(friend.constructor == Person); //false
alert(friend.constructor == Object);    //true

The Problem of Prototype Objects

All the attributes in the prototype are shared. By adding an attribute with the same name to the instance, the corresponding attributes in the prototype (the value of the basic type) can be shielded (only shielded, not changed, but through the prototype object itself). The values of the basic types are stored in the stack memory, and the properties shared by each instance are independent of each other.

function Person(){ 
} 
Person.prototype = { 
    constructor: Person,   
  //Rewriting the prototype object will change the constructor attribute of the instance from pointing to the constructor Person to pointing to Object, where its pointing is defined manually.
    name : "Alex", 
    age : 25, 
    job : " Doctor", 
    friends : ["Shelby", "Court"], 
    sayName : function () { 
        alert(this.name); 
    } 
}; 
var person1 = new Person(); 
var person2 = new Person(); 
person1.name = "Oliver";
console.log(person1.name);  //Oliver
console.log(person2.name);  //Alex  

However, for attributes whose attribute values are reference types, changing the attributes of one instance will also affect the attributes of other instances. These attributes all point to the same attribute value stored in heap memory.

person1.friends.push("Van"); 
alert(person1.friends);    //"Shelby,Court,Van" 
alert(person2.friends);    //"Shelby,Court,Van" 
alert(person1.friends === person2.friends);  //true

6. Combining constructor pattern with prototype pattern

Constructor patterns are used to define instance attributes and methods, and prototype patterns are used to define shared attributes and methods.

function Person(name,age){
    this.name = name;
    this.age = age;
    this.friends = ["Shelby", "Court"]; 
};
Person.prototype = {
    sayName : function(){
        console.log(this.name);
    }
};
var person1 = new Person("Alex",25);
console.log(person1.sayName());   //Alex

var person2 = new Person();
person2.name = "Oliver";
console.log(person2.name);    //Oliver

person1.friends.push("Van"); 
alert(person1.friends);    //"Shelby,Count,Van" 
alert(person2.friends);    //"Shelby,Count"

Improvement

Factory mode, constructor mode, prototype mode and hybrid mode can all pass an object as a parameter.

function Person(option){ 
    this.name = option.name; 
    this.age = option.age; 
    this.job = option.job; 
    this.friends = ["Shelby", "Court"]; 
};
Person.prototype = { 
    constructor : Person, 
    sayName : function(){ 
        alert(this.name); 
    } 
};
var person1 = new Person({
    name: "Alex",
    job: "Doctor"
}); 

Further improvement

Define the _init function in the prototype, and use the _init initialization function to define the attributes that need to be defined in the constructor. Then the _init function is called in the constructor.

function Person(option){
    this._init(option);
}
Person.prototype = {
    _init: function(option){
        this.name = option.name;
        this.age = option.age;
        this.job = option.job; 
        this.friends = ["Shelby", "Court"]; 
    },
    constructor : Person, 
        sayName: function(){
            alert(this.name); 
        }
}
var person1 = new Person({
    name: "Alex",
    job: "Doctor"
}); 

7. Expansion Model

First, you need to customize a extend() function:

/*Expanding an object by copying*/
//Target -- target object
//source -- Stores data that the target object needs to expand
//Add all copies of the data in source to target.
function extend(target,source){
    for( var key in source ){
        target[key] = source[key];
    };
    return target ;
}
/* application */
var Alex = {sex: "male"};
var boy = {name: "Alex", age: 25};

var newAlex = extend(Alex,boy);
console.log(newAlex);   //{sex: "male", name: "Alex", age: 25}

Copy multiple objects to the target object:

// extendMany(target, obj1,obj2,obj3......)
//If no parameters are passed in, the function stops running.
//If only one parameter is passed in, the parameter is assigned to the target and the target is returned. The equivalent is no change;
//If multiple parameters are passed in, the first parameter is the original target object, which copies all the later objects to the target object.
function extendMany(){
    var len = arguments.length;
    var target = null;
    if(len === 0){
        return;
    }else if(len === 1){
        target = this;
    }else{
        target = arguments[0];
    }
    for(var i = 1; i < len; i++){
        for(var key in arguments[i]){
            target[key] = arguments[i][key];
        }
    }
    return target;
}
/* application */
var Alex = {sex: "male"};
var boy = {name: "Alex", age: 25};
var job = {job: "Doctor"};

var newAlex = extendMany(Alex,boy,job);
console.log(newAlex);   //{sex: "male", name: "Alex", age: 25, job: "Doctor"}

8. Use a third-party framework - base2

Creating objects with the following two third-party frameworks eliminates the need to create both constructors and prototypes.

base2 framework

<!-- First, it needs to be introduced. base2 Framework package -->
<script type="text/javascript" src="base2.js"></script>

//Define attributes in constructor methods
var Person = Base.extend({
    constructor: function(name,age){
        this.name = name;
        this.age = age;
    },
    sayName: function(){
        console.log(this.name);
    }
});
var person1 = new Person("Alex", 25);
person1.sayName();   //Alex

simple framework

<!-- First, it needs to be introduced. simplejavascriptinheritance Framework package -->
<script type="text/javascript" src="simplejavascriptinheritance.js"></script>

//Define attributes within init methods
var Person = Class.extend({
    init: function(name,age){
        this.name = name;
        this.age = age;
    },
    sayName: function(){
        console.log(this.name);
    }
});
var person1 = new Person("Alex",25);
person1.sayName();    //Alex

Posted by Tainted Kitten on Sat, 18 May 2019 04:27:57 -0700