原型链学问纪录

此贴用于纪录原型链相干的一些东西。
在JavaScript里,函数都有prototype,对象都有__proto__,一个函数的prototype和一个对象的__proto__就是原型,原型实在也是一个对象。
一个函数的prototype和这个函数的示例对象的__proto__是同一个援用,即:

function A(){
}

let a = new A();
console.log(a.__proto__ === A.prototype); //返回的是true

当挪用某一个对象的要领的时刻,假如找不到这个对象的要领,则会去找这个对象的原型里的要领,假如再找不到,则继续找原型的原型的要领,一向往上找,这个就是原型链,假如都找不到,则会报错。

假如原型链很长,当接见某个属性的时刻,会话更多的时候,须要注重原型链不要太长。

在引入es6的extends之前,函数的继续就是经由过程原型来完成的。下面纪录一下我明白的继续,下面的继续参考的是[JS继续的完成体式格局
][1],他那边有完全的继续要领。

一. 原型链继续

function A(name) {
  this.name = name;
  this.f1 = function () {
    console.log(this.name + '正在做f1');
  }
}
A.prototype.f2 = function () {
  console.log(this.name + '正在做f2');
}

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

B.prototype = new A('');

let b = new B('test');
b.f1();
b.f2();
console.log(b.__proto__ === B.prototype); //true

console.log(b instanceof A);//true
console.log(b instanceof B);//true

上述例子中,b居然是A的实例对象,也是B的实例对象,如许实际上是有题目的,须要在B.prototype = new A(”);背面加上:

B.prototype.constructor = B;

长处:
1.简朴,完成轻易
2.能接见父类一切的要领和属性

瑕玷:
1.要给B的prototype新增要领必需要在 new A(”);以后
2.没法完成多继续
3.没法向父类的组织函数通报参数
4.实例是当前类的实例,也是父类的实例

二. 组织继续

function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + '正在做f1');
  }
}
A.prototype.f2 = function(){
  console.log(this.name + '正在做f2');
}

function B(name) {
  A.call(this, name);
}

let b = new B('test');
b.f1();
// b.f2();// 会报错

console.log(b instanceof A);//false
console.log(b instanceof B);//true

长处:
1.能够运用父类的属性和要领
2.能够完成多重继续,即能够call多个函数
3.实例对象是当前类的实例,不是父类的实例
瑕玷:
1.没法猎取A的prototype的属性和要领
2.只是子类的实例,不是父类的实例
3.没法完成函数复用,每一个子类都有父类实例函数的副本,影响机能(此处应该是挪用call的时刻会天生父类的实例副本,详细的还得再研讨研讨)

三. 组合继续

function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + '正在做f1');
  }
}
A.prototype.f2 = function(){
  console.log(this.name + '正在做f2');
}

function B(name) {
  A.call(this, name);
}
B.prototype = new A('');
//要修改prototype的constructor,为何要修改另有待研讨
B.prototype.constructor = B;

let b = new B('test');
b.f1();
b.f2();

console.log(b instanceof A);//true
console.log(b instanceof B);//true

长处:
1.包含了原型链继续和组织继续的长处
2.处理了原型链继续的没法完成多继续和没法向父类的组织函数通报参数的瑕玷
3.处理了组织继续没法猎取A的prototype的属性和要领另有只是子类的实例,不是父类的实例的题目
瑕玷:
1.挪用了两次父类组织函数,天生了两份实例(子类实例将子类原型上的那份屏障了)

四.寄生组合继续

function A(name){
  this.name = name;
  this.f1 = function(){
    console.log(this.name + '正在做f1');
  }
}
A.prototype.f2 = function(){
  console.log(this.name + '正在做f2');
}

function B(name) {
  A.call(this, name);
}

(function(){
  // 建立一个没有实例要领的类
  var Super = function(){};
  Super.prototype = A.prototype;
  //将实例作为子类的原型,如许就能够只猎取A的prototype的属性了
  B.prototype = new Super();
  //
  B.prototype.constructor = B;
})();

let b = new B('test');
b.f1();
b.f2();

console.log(b instanceof A);//true
console.log(b instanceof B);//true

长处:
1.在组合继续的基础上,只天生了一份父类的实例,prototype也只继续了父类的prototype,没有继续私有的属性
瑕玷:
1.完成庞杂

趁便加一个学问点,当运用new关键字来建立对象的时刻,也用到了原型相干的学问,所以也记在了这里;
假设有一个function A(name){ this.name = name; };运用new关键字建立一个A的实例对象let a = new A();
new关键字重要做了以下几个步骤:
(1)建立一个空的对象
var obj = {};
(2)将这个对象的原型__proto__指向A的prototype
obj.__proto__ = A.prototype
(3)函数A的this指向obj;接着实行A函数
(4)将obj返回,变量a指向obj

本文重如果参考了他人的文章,写一些本身的明白,假如有什么写错的处所迎接大神来斧正一下

    原文作者:上帝遗忘之子
    原文地址: https://segmentfault.com/a/1190000018183162
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞