JS method to create an object

Recently I just finished a project, the next show is still in preparation, take this time to pick up the JS book for many years, review the JS object-oriented programming, and then come to the following, is a summary of it.

You might say, “Isn’t creating an object just a pair of curly braces?” Yes, by far the most common and convenient way to do this is with a pair of curly braces, which is often referred to as a JSON object (not really a JSON object, but we won’t go into details here), as follows:

let obj = {
    name:'xiaohong',
    age: 17,
    gender: 'female'
}
Copy the code

This is what we often call a Literal object method to create an object, should be the most widely used method. This overall method is basically the same as the method below (create Object instance)

let obj = new Object()
obj.name = 'xiaohong'
obj.age = 17
obj.gender: 'female'
Copy the code

However, the Object literal method is simple and intuitive enough to meet the needs of most scenarios, so it is widely used by developers, while the Object instance method is rarely paid attention to. The downside of the literal approach, however, is that there is no reuse at all. If you need to create multiple objects, there is a lot of repetitive code, such as:

var studentA = {
    name: 'xiaohong'
    age: 17,
    gender: 'female'
}
var studentB = {
    name: 'xiaoming'
    age: 18,
    gender: 'male'
}
var studentC = {
    name: 'lili'
    age: 17,
    gender: 'female'
}
Copy the code

As you can see, the only difference between the three objects is the content after the colon. The rest of the code is redundant. Is there any way to avoid this redundancy? In normal development, what do we do when we encounter a feature that needs to be used over and over again? Encapsulate this function as a function and call it repeatedly:

Function Student(name,age,gender){return {name,age,gender} Age :age, gender:gender}} Var studentA = Student('xiaohong',17,'f') var studentB = Student('xiaoming',18,'m') var studentC = studentA = Student('xiaohong',17,'f') var studentB = Student('xiaoming',18,'m') var studentC = Student Student('lili',17,'f')Copy the code

Isn’t that a lot simpler? Every time you call Student, you pass in name, age, gender, and you get the object you want. This method is called the factory model, is it really like a processing plant? This method is useful for creating multiple objects, but it has a disadvantage: it does not know the type of the object, for example, if I want to determine whether studentA is a Student object from the conditional statement

typeof studentA === 'Student'   //false
studentA instanceof Student     // false
Copy the code

Because the factory pattern is too heavy in object recognition, we usually use the constructor pattern to solve the problem of object recognition

Function Student(name,age,gender){this.name = name this.age = age this.gender = gender} Var studentA = new Student('xiaohong',17,'f') var studentB = new Student('xiaoming',18,'m') var studentC = new Student('lili',17,'f')Copy the code

Constructors are similar to those of the factory schema, with two major differences:

  1. Instead of returning an object, we assign the parameter directly to a variable of the same name in the this scope. Since new refers to the instance object from which new was called, the assignment is complete
  2. When a constructor is called, it is preceded by a new (if no new is added, it is used as a normal function, and the scope is assigned to the value in the current code block).

We can detect the type of an object generated by the constructor new

studentA instanceof Student // true
studentA instanceof Object  // true
Copy the code

In fact, js is doing four things behind the scenes when we instantiate a constructor using new:

  1. Create a new object (prototype points to the constructor’s prototype)
  2. Refer to the scope (this) for this object
  3. Execute the constructor code
  4. Return this object

However, constructors are not without their drawbacks. Using constructors to create objects full of data is fine, but what about objects with functions (methods) inside them? Let’s use the code above to modify it slightly. We need to add a learning skill for students:

function Student(name,age,gender){ this.name = name this.age = age this.gender = gender this.study = fucntion() { Console. log(' I'm learning... ')}}Copy the code

At first glance, there is nothing wrong with this. You can also call some instances of study and print “I’m learning…”

Var studentA = new Student('xiaohong',17,'f') studentA. Study () //Copy the code

But if we do this

var studentA = new Student('xiaohong',17,'f')
var studentB = new Student('xiaoming',18,'m')
studentA.study == studentB.study  // false
Copy the code

We find that the studies of the two instances do not refer to the same function, but to two different functions, but their functions are identical equivalent to this

StudentA. Study = fucntion() {console.log(' I'm learning... ')} studentb.study = fucntion() {console.log(' I'm learning... ')} studentc.study = fucntion() {console.log(' I'm learning... ')}Copy the code

How does the OCD take that? It turns out that most people who write code are obsessive-compulsive, so here’s the prototype pattern: I don’t add methods and properties to constructors, I add them directly to constructors’ prototypes, and since the prototypes are shared, we get rid of redundancy here:

Function Student(){} // Declare a null function student.prototype. name = 'xiaohong' student.prototype. age = 17 student.prototype. gender = 'f' student.prototype. study = fucntion() {console.log(' I'm learning... ')} var studentA = new Student() var studentB = new Student() studentA.study == studentA.study // trueCopy the code

In this way, the problem of function duplication is solved, and all instances share the function study on the prototype. All instances will have the same name,age, and gender. This is also not what we want. In this case, you would be wise to put the data in the constructor and only the methods in the prototype:

function Student(name,age,gender){ this.name = name this.age = age this.gender = gender } Student.prototype.study = Fucntion () {console.log(' I'm learning... ')}Copy the code

So put common data declarations inside the constructor, function (method) on the prototype declaration mode, we call it a portfolio model constructor (i.e., use a combination of model and prototype model), combination mode, both data independence, and there are ways of sharing A object creation can be said to be more perfect. ES6’s class syntax sugar implementation is also largely based on composite patterns.

The above are some common patterns for creating objects in ES5, but there are also some unusual patterns, such as dynamic prototype, parasitic constructor, safe constructor… And so on, here is not a list, interested in children’s shoes baidu about

Well, that’s all for creating objects, thanks for watching!

If you think it is useful, please add a star to github of this article, thank you very much. In addition, there are some other tutorials and components about front-end on Github, interested children can have a look, your support is my biggest motivation.