如何理解原型 && 继承 && class

244 阅读4分钟

1:如何理解原型

javascript规定,每一个函数都有一个prototype对象属性,指向另一个对象(原型链上的)。(指向的是实例对象的__prpto__)
prototype上的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些公共的属性和方法,直接定义在prototype上

prototype可以让所有对象实例共享它所包含的属性和方法。也就是说,
不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中去。

2:如何理解原型链

实例对象与原型之间的连接,叫做原型链。proto(隐式连接)

js在创建对象的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype

内部原型(proto)和构造器的原型(prototype)
(1)每个对象都有一个proto属性,原型链上的对象正是依靠这个属性连接在一起

(2)作为一个对象,当你访问其中一个的属性或者方法的时候,如果这个对象中没有这个方法或者属性,那么js引擎会访问这个对象的proto属性所指的上一个对象,并在那个对象中查找指定的方法或属性,如果找不到,那就会继续通过那个对象的proto属性 指向的对象进行向上查找,直到这个链表结束

(3)由于__proto__是任何对象都有的属性,而js里万物皆对象,所以会形成一条__proto__连起来的链条,递归访问__proto__必须最终到头,并且值是null

当js引擎查找对象的属性时,先查找对象本身是否存在该属性,如果不存在,会在原型链上查找,但不会查找自身的prototype

原型链的顶层就是Objec.prototype 


3:如何理解constructor/instanceof/proto/prototype

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

var person = new Person('tom')

// 沿着对象的person的__proto__属性 --> 到原型链终端

__proto__:隐式属性,对象的属性,指向这个对象构造函数的原型

constructor:查看实例对象的构造函数

instanceof:
A instanceof B
//判断A对象是不是B构造函数构造出来的
//实质是看A对象的原型链上有没有B的原型

hasOwnProperty:判断属性是否是继承过来的
for(var prop in obj) {
    if(obj.hasOwnPrototype(prop)){
        console.log(obj[prop])
    }
}

3: 什么是继承

一个类获取另一个或者多个类的属性或者方法。
继承可以使得子类具有父类的各种方法和属性,以免重复输出很多代码

4:实现继承的原理

复制父类的方法和属性来重写子类的原型对象

5:怎么实现继承

  • 1:原型链继承

  • 2:借用构造函数call/apply

  • 3:圣杯模式

  • 4:class-es6语法

1:原型链继承
Person.prototype.text = 'hehe'
function Person(name,age){
    this.name = name;
    this.age = age
}

function CopyPerson(){
    
}

CopyPerson.prototype = Person.prototype
var person = new CopyPerson();

var inhert_person = new Person();
CopyPerson.prototype = inhert_person
2:借用构造函数call/apply(改变this指向)
function Person(name,age){
    this.name = name;
    this.age = age
}
function CopyPerson(name,age,sex){
    Person.call(this,11)
}
var person = new CopyPerson(11,22,33)

3:圣杯模式
function inheritFunc(origin,target){
     
    function func(){
        
    }
    func.prototype = origin.prototype;
    
    target.prototype = new func();
    target.prototype.constructor = Target;
    
}

6:class的继承

es5的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面。 Parent.apply(this) Es6的继承机制完全不同,实质是先将父类实例对象的属性和方法,添加到this上面(所以必须先调用super方法) 然后在用子类的构造函数修改this

class Point {
    constructor(name,age) {
        this.name = name;
        this.age = age;
    }
    toString() {
        return this.name + this.age
    }
}

class colorPoint extends Point {
    constructor(name,age,sex){
        super(name,age) // 调用父类的constructor
        this.sex = sex
    }
}

class A {
    
}
class B extends A {
    constructor(){
        super()
    }
}

7:es6的class实现继承的原理

class作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此存在两条继承链

  • (1)子类的__proto__属性,表示构造函数的继承,总是指向指向父类
  • 子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype

##8: es5继承和es6继承的区别

es5的继承,实质上是先创造子类的实例对象this
然后再将父类的方法添加到this上面

es6的继承机制完全不同,实质是先将父类实例对象的属性和方法加到this上面
(所以必须先调用super方法),然后在用子类的构造函数修改this