20170607 - Object Oriented 01 - Object Creation

create object

1.Object constructor

Create an instance of Object by adding attributes and methods to it (the pattern for creating objects early)

var person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";

person.sayName = function(){
    alert(this.name);

}

2. Object literals

var person = {
    name: "Nicholas";
    age: 29;
    job: "Software Engineer";
    
    sayName: function(){
        alert(this.name);
    }
}

Two early methods of creating objects are mentioned: Object constructors and object literals, but these methods have obvious drawbacks: creating many objects with the same interface will generate a lot of duplicate code.

3. Factory mode:

function createPerson(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    }
    return o;
}
var person1 = create("Nicholas", 29, "Software Engineer");

Disadvantages:

  • Although the factory pattern solves the problem of creating multiple similar objects with a large amount of duplicate code, it does not solve the problem of Object recognition (because the Object types are returned).

4. Constructor pattern

Constructors in ECMAScript can be used to create specific types of objects.

function Person(name, age, job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=function(){
        alert(this.name);
    }
}
// Note that using Person as a constructor requires the use of the new operator to create new objects
var person1 = new Person("xin",22,"Software Engineer");
var person2 = new Person("wu",22,"Software Engineer");

In the above example, person1 and person2 hold a different instance, respectively, but both objects have a constructor (constructor) property that executes Person.

Detection object type:

  • Using the constructor attribute:

alert(person1.constructor == Person); //true
  • Using the instanceof operator:

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

Creating a custom constructor means that its instances can be identified as a specific type in the future

Disadvantages:

  • Each method is recreated on each instance. In the example above, both person1 and person2 have a sayName method, but the method in both instances is not an instance of the same Function. Therefore, functions of the same name on different instances are not equal.

  • Solution: Transfer the function definition to the outside of the constructor.

function Person(name, age, job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=sayName;//SayName property set to global sayName function
}
function sayName(){
        alert(this.name);
}
var person1 = new Person("xin",22,"Software Engineer");
var person2 = new Person("wu",22,"Software Engineer");
  • After modification, the person1 and person2 objects share the same sayName() function defined in the global scope. But new problems arise:

    • In fact, the function defined in the global scope (sayName) can only be called by an object (person1 person2), which makes the global scope "inappropriate".

    • If an object needs to define many methods, it needs to define many global functions in the global scope, so that this custom reference type (custom constructor) is not encapsulated.

    • Solution: prototype mode

5. Prototype Model

Each function has a prototype attribute, which is a pointer to an object whose purpose is to contain properties and methods that can be shared by all instances of a particular type.

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.ptototype.sayName = function(){
    alert(this.name);
}
var person1 = new Person();
person1.sayName(); //"Nicholas"

var person2 = new Person();
person2.sayName();//"Nicholas"
//The attributes and methods of person1 and person2 are shared by all instances
alert(person1.sayName == person2.sayName); //true

Understanding prototype objects

Access to Prototype Property [[Prototype]]

  • Determining the relationship between objects is Prototype Of

alert(Person.prototype.isPrototypeOf(person1));//true
  • Get the prototype object Object. getPrototype Of ()

alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name);//Nicholas
  • Every time 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, continue searching for the prototype object pointed by the pointer and find properties with a given name in the prototype object. If the value of the property is found in the prototype object, the value of the property is returned.

  • Although the values stored in the prototype can be accessed through object instances, they cannot be overridden by objects. If an attribute is added to the instance and the attribute has the same name as an attribute in the instance prototype, the attribute masks that attribute in the prototype.

  • The hasOwnProperty() method can be used to detect whether an attribute exists in an instance or in a prototype.

`
person1.hasOwnProperty("name"); //false
`

  • Prototype and in operator: When the in operator is used alone, the in operator returns true when a given attribute can be accessed through the prototype, whether it exists in the instance or in the prototype. The hasOwnProperty() method and in operator are used to determine whether the attribute exists in the object or in the prototype.

alert( !person1.hasOwnProperty(name) && name in person1); //true

Simpler prototype grammar:

In the previous example, for each attribute and method added, the Person.prototype is typed once. To reduce unnecessary input, a more common approach is to rewrite the entire prototype object with an object literal that contains all the attributes and methods.

function Person(){
}
Person.prototype = {
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function(){
        alert(this.name);
    }
}

Be careful:
The syntax used here essentially completely rewrites the default prototype object, so the constructor attribute becomes the constructor attribute of the new object (pointing to the Object constructor) and no longer points to the Person function. Using the instanceof operator also returns the correct result, but the type of the object can no longer be determined by the constructor.

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

If the constructor attribute is important, you can set it to the appropriate value

//Method 1, but makes the [[Enumerable]] property of the constructor attribute true
function Person(){
}
Person.prototype = {
    constructor:Person,
    name:"Nicholas",
    age:29,
    job:"Software Engineer",
    sayName:function(){
        alert(this.name);
    }
}
function Person(){
}
Person.prototype = {
    name:"Nicholas",
    job:"Software Engineer",
    age:29,
    sayName:function(){
        alert(this.name);
    }
}
Object.defindProperty(Person.prototype, "constructor",{ 
    enumerable: false,
    value: Person
});

Prototype of native object:

All native types (Object,Array,String, etc.) define methods on the prototype of their constructors.

The problem of prototype objects:

  • Passing parameters to constructors is omitted, resulting in all instances getting the same attribute value by default.

  • The biggest problem of prototype objects is caused by the nature of their shared attributes:

function Person(){
}
Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    friends: ["Sheldon","Court"],
    sayName: function(){
        alert(this.name);
    }
};
var person1 = new Person();
var person2 = new Person();

person1.friends.push("van");
alert(person1.friends); //sheldon,court,van
alert(person2.friends); //sheldon,court,van
alert(person1.friends === person2.friends);//true

The reason for this problem is that the friends properties of person1 and person2 share an array.

6. Combining constructor pattern with prototype pattern

The constructor pattern defines instance attributes, and the prototype pattern defines methods and shared attributes. As a result, each instance will have its own copy of the instance attributes, but at the same time share the reference to the method, which saves the memory to the greatest extent.

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["sheldon","mary"];
}
Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
}

7. Dynamic prototype model

Combining constructor pattern with prototype pattern is the most widely used method to create custom types, but it defines attributes and methods separately (independent constructors and prototypes). This problem can be solved by using dynamic prototype pattern, encapsulating all information in the constructor, initializing prototypes in the constructor, and maintaining the use of constructors and prototypes. Advantages.


function Person(name, age, job){
    this.name = name
    this.age = age
    this.job = job
    
    // This code will only be executed when the constructor is first called
    if(typeof this.sayName === "function"){
        Person.prototype.sayName = function(){
            alert(this.name)
        }
    }
}

var friend = new Person('xin', 29, "Softwar Engineer")
friend.sayName()

8. Steady constructor model

  • Features: 1. The instance method of the newly created object does not refer to this; 2. Calling the constructor without using the new operator

function Person(name,age,job){
    var o = new Object();
    o.sayName = function(){
        alert(name);
    }
    return o;
}
  • In objects created in this way, there is no way to access the value of name except by using the sayName() method.

var friend = Person("Nicholas",29,"Software Engineer");
friend.sayName();

Even if other code adds methods or data members to the object, there is no other way to access the raw data (name,job,age) that is passed into the constructor. The security provided by the secure constructor pattern makes it very suitable for execution in some secure environments.

Objects created using a prudent constructor pattern have little to do with constructors, so the instanceof operator makes little sense for such objects.

Keywords: Javascript Attribute ECMAScript

Added by metkat on Tue, 25 Jun 2019 00:47:29 +0300