1. What is the object

Object Oriented Programming (OOP) is the mainstream Programming paradigm. It abstracts all kinds of complex relationships in the real world into objects, and then completes the simulation of the real world through the division of labor and cooperation between objects.

Each object is a function center with a clear division of labor, which can complete tasks such as receiving information, processing data and sending information. Objects can be reused and customized through inheritance mechanisms. Therefore, object-oriented programming is flexible, reusable, highly modular and easy to maintain and develop. Compared with traditional procedural programming composed of a series of functions or instructions, it is more suitable for large-scale software projects with multiple people.

So what exactly is an object? We understand it on two levels.

(1) An object is an abstraction of a single object.

A book, a car, a person can all be objects, as can a database, a web page, a connection to a remote server. When objects are abstracted into objects, the relationship between objects becomes the relationship between objects, so that the real situation can be simulated and the object can be programmed.

(2) An object is a container that encapsulates properties and methods.

Properties are the state of the object, and methods are the behavior of the object (to accomplish something). For example, we can abstract an animal as an animal object, using “attributes” to record which animal it is, and “methods” to represent certain behaviors of the animal (running, hunting, resting, etc.).

2. Constructor

The first step in object-oriented programming is to generate objects. As mentioned earlier, an object is an abstraction of a single object. You usually need a template that represents common characteristics of a class of objects from which objects are generated.

Typical object-oriented programming languages, such as C++ and Java, have the concept of a class. A class is a template of an object, and an object is an instance of a class. However, the object architecture of the JavaScript language is not based on “classes”, but on constructors and prototype chains.

The JavaScript language uses constructors as templates for objects. A “constructor” is a function specifically used to generate instance objects. It is the template of the object and describes the basic structure of the instance object. A constructor that generates multiple instance objects, all of which have the same structure.

A constructor is an ordinary function, but it has its own characteristics and uses.

var Vehicle = function () {
	this.price = 1000;
};
Copy the code

In the above code, Vehicle is the constructor. To distinguish constructor names from normal functions, the first letter is usually capitalized.

Constructors have two characteristics:

  • 1. This keyword is used inside the function body to represent the instance of the object to be generated.
  • 2. When generating objects, you must use the new command.

Let’s start with the new command.

3. The new command

3.1 Basic Usage

The new command executes a constructor that returns an instance object.

var Vehicle = function () {
	this.price = 1000;
};

var v = new Vehicle();
v.price  / / 1000
Copy the code

Using the new command, the constructor Vehicle generates an instance object, which is stored in variable v. The newly generated instance object gets the price attribute from the constructor Vehicle. When the new command is executed, this inside the constructor represents the newly generated instance object. This. price indicates that the instance object has a price attribute with a value of 1000.

When using the new command, the constructor can also accept arguments as needed.

var Vehicle = function (p) {
  this.price = p;
};

var v = new Vehicle(500);
Copy the code

The new command executes the constructor itself, so the following constructor may or may not be parenthesized. The following two lines of code are equivalent, but to indicate that this is a function call, parentheses are recommended.

// The recommended way to write it
var v = new Vehicle();
// Not recommended
var v = new Vehicle;
Copy the code

A natural question is what happens if you forget to use the new command and call the constructor directly?

In this case, the constructor becomes a normal function and does not generate instance objects. And for reasons we’ll see later, this represents a global object, which can cause some unexpected results.

var Vehicle = function (){
  this.price = 1000;
};

var v = Vehicle();
v // undefined
price / / 1000
Copy the code

In the above code, we forgot to add the new command when calling the Vehicle constructor. As a result, the variable v becomes undefined and the price attribute becomes a global variable. Therefore, you should be very careful not to call the constructor directly without using the new command.

To ensure that the constructor must be used with the new command, one solution is to use strict mode inside the constructor, with use strict on the first line. That way, if you forget to use the new command, calling the constructor directly will return an error.

function Fubar(foo, bar){
  'use strict';
  this._foo = foo;
  this._bar = bar;
}

Fubar()
// TypeError: Cannot set property '_foo' of undefined
Copy the code

The Fubar of the code above is a constructor, and the use strict command ensures that the function runs in strict mode. Because in strict mode, this inside a function cannot refer to a global object and is equal to undefined by default, the call without new will result in an error (JavaScript does not allow adding attributes to undefined).

As an alternative, the constructor internally determines whether to use the new command and returns an instance object if it does not.

function Fubar(foo, bar) {
  if(! (this instanceof Fubar)) {
    return new Fubar(foo, bar);
  }

  this._foo = foo;
  this._bar = bar;
}

Fubar(1.2)._foo / / 1
(new Fubar(1.2))._foo / / 1
Copy the code

The constructor in the above code, with or without the new command, yields the same result.

3.2 Principle of the new command

When the new command is used, the functions that follow it perform the following steps.

  1. Creates an empty object as an instance of the object to be returned.
  2. Point the empty object’s prototype to the constructor’sprototypeProperties.
  3. Assigns this empty object to the internalthisThe keyword.
  4. Start executing the code inside the constructor.

That is, inside the constructor, this refers to a newly generated empty object on which all operations will be performed. A constructor is called a “constructor” because its purpose is to manipulate an empty object (this object) and “construct” it into what it needs to look like.

If the constructor has a return statement inside it, and the return is followed by an object, the new command returns the object specified by the return statement. Otherwise, this object is returned regardless of the return statement.

var Vehicle = function () {
  this.price = 1000;
  return 1000;
};

(new Vehicle()) === 1000
// false
Copy the code

In the code above, the return statement of the constructor Vehicle returns a number. The new command ignores the return statement and returns the “constructed” this object.

However, if the return statement returns a new object unrelated to this, the new command returns the new object, not this. This requires special attention.

var Vehicle = function (){
  this.price = 1000;
  return { price: 2000 };
};

(new Vehicle()).price
/ / 2000
Copy the code

In the above code, the return statement of the constructor Vehicle returns a new object. The new command returns this object instead of this.

On the other hand, using the new command on ordinary functions (functions that do not have the this keyword inside them) returns an empty object.

function getMessage() {
  return 'this is a message';
}

var msg = new getMessage();

msg / / {}
typeof msg // "object"
Copy the code

In the above code, getMessage is a normal function that returns a string. Use the new command on it, and you get an empty object. This is because the new command always returns an object, either an instance object or an object specified by the return statement. In this case, the return statement returns a string, so the new command ignores it.

The internal process simplified by the new command can be represented in the following code.

function _new(/* Constructor */ constructor, /* Constructor argument */ params) {
  // Convert arguments objects to arrays
  var args = [].slice.call(arguments);
  // Get the constructor
  var constructor = args.shift();
  // Create an empty object that inherits the constructor's Prototype property
  var context = Object.create(constructor.prototype);
  // Execute the constructor
  var result = constructor.apply(context, args);
  If the result is an object, return it directly, otherwise return the context object
  return (typeof result === 'object'&& result ! =null)? result : context; }/ / instance
var actor = _new(Person, 'Joe'.28);
Copy the code

3.3 the new target

You can use the new.target attribute inside the function. If the current function is called with the new command, new.target points to the current function, otherwise undefined.

function f() {
  console.log(new.target === f);
}

f() // false
new f() // true
Copy the code

Use this attribute to determine whether the new command is used when the function is called.

function f() {
  if (!new.target) {
    throw new Error('Please call with the new command! ');
  }
  // ...
}

f() // Uncaught Error: Please call with new command!
Copy the code

In the above code, an error is thrown when the constructor f is called without using the new command.

4. Object.create() creates the instance Object

The constructor functions as a template to generate instance objects. However, sometimes the constructor is not available, and only an existing object is available. We want to use this existing Object as a template to generate a new instance Object, using the object.create () method.

var person1 = {
  name: 'Joe'.age: 38.greeting: function() {
    console.log('Hi! I\'m ' + this.name + '. '); }};var person2 = Object.create(person1);

person2.name / / zhang SAN
person2.greeting() // Hi! I 'm zhang SAN.

Copy the code

In the code above, the object Person1 is a template for Person2, which inherits its properties and methods.

For a detailed description of object.create (), see the relevant sections below.

reference

Reprinted in ruan Yifeng’s blog. Javascript.ruanyifeng.com/oop/basic.h…