JS prototype, prototype inheritance, understanding the prototype chain

Foreword

For the prototype, the prototype chain, prototypal inheritance, is a basis for each front-end staff will be off. Almost always asked during the interview prototype, the prototype chain of these questions, simply write about the article, the one-time understand these issues clearly (see other people's articles many times, it is better to actually write about, know when to see, it can be over two days will be forgotten).

Prototype understanding

We created 每个函数都有一个prototype(原型)属性, this property is 一个指针,指向一个对象, the object and purpose of this is to encompass all instances of a particular type 共享的属性和方法. prototype (prototype) is 通过调用构造函数而创建的那个对象实例的原型对象. The benefits of using the prototype object is that it gives all the properties and methods of objects it contains examples of sharing.

function Animal(){}

Animal.prototype.name = 'animal';
Animal.prototype.age = '10';
Animal.prototype.sayName = function(){
    console.log(this.name);
}

let dog = new Animal();
dog.sayName();          // 输出 animal
let cat = new Animal();
cat.sayName();          // 输出 animal
复制代码

The above explained a prototype using a code sharing properties and methods . The properties and methods are added to the prototype Animal's constructor function becomes empty. Whether dog instances Animal (), or cat instances Animal (), have access to the same set of attributes and the same sayName () function. When adding a property of an object instance, the shielding property of the same name will be stored in prototype object attributes.

function Animal(){}
// 常用原型写法
Animal.prototype = {
    name: 'animal',
    age: '10',
    sayName: function(){
    	console.log(this.name);
    }
};

let dog = new Animal();
dog.sayName();          // 输出 animal
let cat = new Animal();
cat.name = 'Tom';
cat.sayName();          // 输出 Tom
复制代码

I mentioned earlier: the prototype (prototype) is the prototype of an object that object created by calling the constructor instances. By default, all automatically obtain a prototype object constructor (the constructor) property, which contains a pointer to where the pointer to the function prototype property. As shown below:

Animal Each instance of dog and cat contains an internal attribute 仅仅指向了Animal.prototype; in other words, they are not directly related to the constructor.

Understanding the prototype chain

The basic idea is to use the prototype chain prototype to make a reference type inherits from another type of reference properties and methods. A brief review of the relationship between constructor, prototype and examples: Each constructor function has a prototype object, the prototype object contains a pointer pointing to the constructor, and the instance contains an internal pointer to the prototype object.

function Animal(){}
// 常用原型写法
Animal.prototype = {
    name: 'animal',
    age: '10',
    sayName: function(){
    	console.log(this.name);
    }
};

// 继承Animal,实际上就是重写原型
function runAnimal(){}
runAnimal.prototype = new Animal();
runAnimal.prototype.run = function(){
	console.log("我会跑!!!");
}

let cat = new runAnimal();
console.log(cat.name);      // 输出 animal
console.log(cat.run());     // 输出 我会跑!!!
复制代码

We know that all reference types are inherited by default Object, and this is inherited through the prototype chain to achieve. Therefore, the above can be converted to the inheritance FIG:

Prototypal inheritance

Subclass prototype parent class object instance

The basic idea: use the prototype to make a reference type inherits from another type of reference properties and methods. Examples of the prototype of the prototype parent class by subclasses.

function Animal(){
    this.behavior = ['吃饭', '睡觉'];
}
// 常用原型写法
Animal.prototype = {
    name: 'animal',
    age: '10',
    sayName: function(){
        console.log(this.name);
    }
};

// 继承Animal,实际上就是重写原型、原型实例化父类
function runAnimal(){}
runAnimal.prototype = new Animal();
runAnimal.prototype.run = function(){
	console.log("我会跑!!!");
}

let cat = new runAnimal();
console.log(cat.name);      // 输出 animal
console.log(cat.run());     // 输出 我会跑!!!
console.log(cat.behavior);  // ["吃饭", "睡觉"]

let dog = new runAnimal();
dog.behavior.push('咆哮');
console.log(dog.behavior); // ["吃饭", "睡觉", "咆哮"]

console.log(cat.behavior); // ["吃饭", "睡觉", "咆哮"]  =>关注点
复制代码

Disadvantages:

  • Change the instance of a subclass of a subclass inherits from the parent class prototype constructor to the common attributes will directly affect other subclasses.
  • In creating the instance subtype, can not pass parameters to the constructor of the supertype. In fact, it should be said there is no way in without affecting all object instances, to super type constructor pass parameters.

Constructors Inheritance

The basic idea is quite simple, that is to call the constructor in the super-type internal sub-type constructor. Do not forget, functions are just objects to execute code in a specific environment, so by using the apply () and call () method can also be executed in the constructor on the object (in the future) newly created.

// 父类
function Animal(id){
    this.behavior = ['吃饭', '睡觉'];
	this.id = id;
}
Animal.prototype = {
    name: 'animal',
    age: '10',
    sayName: function(){
        console.log('我的编号是:'+this.id);
    }
};

// 声明子类
function childAnimal(id){
	// 继承父类
	Animal.call(this, id);
}

let cat = new childAnimal(100);
console.log(cat.id);      // 输出 100
console.log(cat.behavior);  // ["吃饭", "睡觉"]

console.log(cat.name);  // undifined    =>关注点
console.log(cat.sayName()); // error!!! =>关注点

let dog = new childAnimal(101);
dog.behavior.push('咆哮');
console.log(dog.id);      // 输出 101
console.log(dog.behavior); // ["吃饭", "睡觉", "咆哮"]

console.log(cat.behavior); // ["吃饭", "睡觉"] =>关注点
复制代码

Advantages and disadvantages

  • Borrowing constructor has a great advantage that you can pass parameters to a constructor in the super-type sub-type constructor.
  • Methods defined in the super-type prototype, with respect to the sub-type is not visible, the results of all types can only use the constructor mode.

A combination of inheritance

It refers to a combination of technology and borrow prototype chain to a constructor, both of which play a long one of the inheriting mode. Idea behind it is a prototype of the prototype implementation inheritance chain properties and methods, and to achieve an instance attribute inherited by borrowed constructor.

// 父类
function Animal(id){
    this.behavior = ['吃饭', '睡觉'];
    this.id = id;
}
Animal.prototype = {
    name: 'animal',
    age: '10',
    sayName: function(){
        console.log('我的编号是:'+this.id);
    }
};

// 声明子类
function childAnimal(id){
    // 构造函数继承父类
    Animal.call(this, id);
}

// 子类的原型对象实例父类
childAnimal.prototype = new Animal();

let cat = new childAnimal(100);
console.log(cat.id);      // 输出 100
console.log(cat.behavior);  // ["吃饭", "睡觉"]

console.log(cat.name);  // animal     =>关注点,区别之处
console.log(cat.sayName()); // 我的编号是: 100  =>关注点,区别之处

let dog = new childAnimal(101);
dog.behavior.push('咆哮');
console.log(dog.id);      // 输出 101
console.log(dog.behavior); // ["吃饭", "睡觉", "咆哮"]

console.log(cat.behavior); // ["吃饭", "睡觉"]  =>关注点
复制代码

Advantages and disadvantages

  • Combination of inherited and avoids borrowing constructor prototype chain defects, combines their advantages, JavaScript has become the most commonly used mode of inheritance. Further, instanceof and isPrototypeOf () it can also be used to identify objects created based on the combined inheritance.
  • The biggest problem is the combination of inheritance Whatever the case, calls the two types of super constructor: once when creating the subtype prototype, and once inside the sub-type constructor.

Prototypal inheritance

Prototypal inheritance idea is to create a new object by means of a prototype based on existing objects, but also do not have to therefore create a custom type.

// 道格拉斯·克罗克福德给出的函数
function object(o){ 
    function F(){} 
    F.prototype = o; 
    return new F(); 
}
复制代码

Essentially, object () to perform a shallow copy of the incoming object of them.

function book(obj) {
	function F(){};
	F.prototype = obj;
	return new F();
}

let HTML5 = {
	name: 'HTML5 高级程序设计',
	author: ['Peter Lubbers', 'Ric Smith', 'Frank Salim']
};

let myNewBook = new book(HTML5);
console.log(myNewBook.name); // HTML5 高级程序设计
myNewBook.author.push('Brian Albers');
console.log(myNewBook.author); // ["Peter Lubbers", "Ric Smith", "Frank Salim", "Brian Albers"]

let otherBook = new book(HTML5);
otherBook.name = "VUE";
otherBook.author.push('尤');

console.log(otherBook.name); // VUE
console.log(otherBook.author); // ["Peter Lubbers", "Ric Smith", "Frank Salim", "Brian Albers", "尤"]

console.log(myNewBook.author); // ["Peter Lubbers", "Ric Smith", "Frank Salim", "Brian Albers", "尤"]
复制代码

Advantages and disadvantages

  • The parent class object book attribute value type is assigned, a reference type attribute are commonly used. Reference type attribute value will always share corresponding value, as using the same prototype mode.

Parasitic inheritance

Parasitic inherited ideas and parasitic constructors and factory pattern is similar, only the creation of a succession process for encapsulating function, the function internally in some way to enhance the object, and finally it is really like to do all the work, like return the object.

function createAnother(original){ 
    var clone = object(original); //通过调用函数创建一个新对象
    clone.sayHi = function(){ //以某种方式来增强这个对象
        console.log("hi"); 
    }; 
    return clone; //返回这个对象
}

var person = { 
    name: "Nicholas", 
    friends: ["Shelby", "Court", "Van"] 
}; 
var anotherPerson = createAnother(person); 
anotherPerson.sayHi(); //"hi"
复制代码

Combined parasitic inheritance

The so-called parasitic combined inheritance, i.e., inherit attributes borrowed constructor method to blend inherited form prototype chain. The basic idea behind it is: do not have to specify the subtype of the type of prototype and call the super constructor, we need nothing more than a copy of the super-type prototype only. In essence, it is the use of Parasitic inheritance to inherit the super-type prototype, and then assign the result to a subtype of the prototype.

// 定义父类
function SuperClass (name){
    this.name = name;
    this.colors = ["red","blue","green"];
}
// 定义父类原型方法
SubClass.prototype.getName = function () {
    console.log(this.name);
}
// 定义子类
function SubClass (name, time){
    SuperClass.call (this, name); // 构造函数式继承
    this.time = time; // 子类新增属性
}

function inheritPrototype(subType, superType){ 
    var prototype = object(superType.prototype);  // 创建对象
    prototype.constructor = subType;  // 增强对象
    subType.prototype = prototype;  // 指定对象
}

// 寄生式继承父类原型
inheriPrototype(SubClass, SuperClass);
// 子类新增原型方法
SubClass.prototype.getTime = function (){
    console.log(this.time);
};
// 创建两个测试方法
var instance1 = new SubClass("js book", 2018);
var instance2 = new SubClass("css book", 2019);

instance1.colors.push("black");
console.log(instance1.colors);  // ["red","blue","green","black"]
console.log(instance2.colors);  // ["red","blue","green"]
instance2.getName ();   // css book
instance2.getTime ();   // 2019
复制代码

to sum up

Own little red book slowly read it again, to manually knocked on the code, basically the prototype can be understood, badly written, please correct me. Prototype, the prototype chain, prototype inheritance personal feeling is mixed together, put the prototype, it will put the prototype chain, prototype inheritance. 10 times better to see yourself knocked code memories will be more profound problem appeared in the middle also make you shines (for example, you often use this point to the problem).

Reference material

  • JavaScript Advanced Programming (3rd Edition)

Reproduced in: https: //juejin.im/post/5cef3b3b518825526b294b6b

Guess you like

Origin blog.csdn.net/weixin_33911824/article/details/91441861