What is the prototype

  • allReference typesThere is a__proto__(implicit prototype)Property, the property value is a normal object
const arr = []
console.log(typeof arr.__proto__); // object
Copy the code
  • allReference typesthe__proto__attributePoint to theitConstructor prototype
console.log(arr.__proto__ === Array.prototype); // true
Copy the code
  • When an object looks for an attribute, it will look up its prototype based on __proto__, ending atObject.prototype.__proto__fornullThe search process forms the prototype chain
console.log(arr.toString); // [Function: toString]
Copy the code

Exploration prototype chain

You can go to the Birth of Everything in JavaScript, a great article to help you understand the prototype chain 👀

Here’s the root of all evil

  • Why do we need prototypes and prototype chains
function Person(name) {
  this.name = name;
  this.sayname = function() {
    console.log(name); }}let p1 = new Person('xguo');
let p2 = new Person('xguo');

console.log(p1.sayname === p2.sayname); // false
Copy the code

Generating instance objects with constructor calls has the disadvantage of not sharing properties and methods. Each instance object has its own copy of properties and methods. Not only was this data unshareable, it was also a huge waste of resources, and with that in mind, prototypes and prototype chains were born

function Person(name) {
  this.name = name;
}

Person.prototype.sayname = function() {
  console.log(The '-');
}

let p1 = new Person('xguo');
let p2 = new Person('xguo');

console.log(p1.sayname === p2.sayname); // true
Copy the code
  • How to understand prototype chains

Object.prototype.__proto__ === null Typeof null === ‘object’; typeof null == ‘object’; So ES5 uses Object.create(null) to generate empty objects with no archetypes

console.log(Object.prototype.__proto__ == Object.create(null).__proto__); // true
Copy the code

That is, Object. Prototype is generated this way and then tied to Object’s Prototype properties because objects can be modified and then assigned new properties

console.log(Function.__proto__=== Function.prototype); // true
Copy the code

Function is a Function, and as long as it is a Function, its __proto__ refers to Funtion. Prototype that is the inherited setting. Function is generated without a __proto__ attribute. It is a BOM object. The __proto__ and prototype attributes of Function refer to the same BOM object later

console.log(Object instanceof Function) // true
console.log(Object.__proto__=== Function.prototype); // true
Copy the code

Object is a constructor function, so its __proto__ property points to Funtion. Prototype

function Person() {}
console.log(typeof Person.prototype);
console.log(typeof Function.prototype);
Copy the code

Function. Prototype is a Function (prototype), and the rest are normal objects. It’s a bridge. We’ve been saying that functions are objects, and only if this satisfies, can a function be an object

“Constructor” new

function Cat(name, color) {
    // Encapsulation like other languages lowers the barrier for developers of other languages
    this.name = name
    this.color = color
}

var cat1 = new Cat('the dog egg'.'white')
console.log(cat1.constructor === Cat); // true
Copy the code

We use the new keyword, which appears to execute the class’s constructor method, capitalize Cat, and cat1.constructor === Cat, all as if it were a class

  • The constructor is still called

In fact, Cat is no different from any other function in the program. The trick is New, which hijacks all ordinary functions and calls them as constructs. In other words, the most accurate definition of “constructor” in JavaScript is all function calls with new

  • The constructor property
console.log(cat1.constructor === Cat.prototype.constructor); // true
Copy the code

In fact, the prototype. The constructor default point to the Cat, this has nothing to do and “structure”.

function Cat() {}
Cat.prototype = {}

var cat1 = new Cat()
console.log(cat1.constructor === Cat); // false
console.log(cat1.constructor === Object); // true
Copy the code

The.constructor property is only the default property of the Cat function when it is declared. If you create a new object and replace the function’s default. Prototype reference, the new object does not automatically acquire the.constructor property

  • Manual implementation of a simplified version of new
function Person(name, age, sex="Female") {
    // console.log(arguments)
    this.name = name;
    this.age = age;
    this.sex = sex;
}
// Instances have their own (private) constructor via prototype except for attributes
// Method shared between objects (prototype)
// Construtor completes an object construction and connects the shared method using Prototype

Person.prototype.sayHi = function() {
    console.log('Hello.');
}
// Implement new manually
const objectFactory = function() {
    var obj = new Object(a);Shift [] Method on the shift object
    // this -> [] call -> arguments
    // console.log(Array.from(arguments).shift());
    var varConstructor = [].shift.call(arguments); varConstructor.call(obj, ... arguments); obj.__proto__ = varConstructor.prototype;return obj;
}

const obj = objectFactory(Person, 'xguo'.19.'male');
console.log(obj); // Person {name: 'xguo', age: 19, sex: 'male '}
obj.sayHi(); / / hello
Copy the code