美文网首页
原型链和class继承

原型链和class继承

作者: 一头会飞的大象 | 来源:发表于2020-03-01 20:54 被阅读0次

从网上找了一张图,比较清楚的描述了原型链


愿型链

原型链

1.原型链的定义

每个对象都可以有一个原型proto,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找...... 这个操作被委托在整个原型链上,这个就是我们说的原型链了。

2.原型指针

接下来我们先理解以下这三个属性prototype__proto__constructor

  • prototype:
    prototype属性,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象; 这个属性是一个指针,指向一个对象,这个对象的用途就是包含所有实例共享的属性和方法(我们把这个对象叫做原型对象);
  • __proto__:
    __proto__ 是原型链查询中实际用到的,它总是指向 prototype,换句话说就是指向构造函数的原型对象,它是对象独有的。注意,为什么Foo构造也有这个属性呢,因为在js的宇宙里万物皆对象,包括函数;
  • constructor:
    每个函数都有一个原型对象,该原型对象有一个constructor属性,指向创建对象的函数本身(构造函数)。所有的实例对象都可以访问constructor属性,constructor属性是创建实例对象的函数的引用。

prototype 是函数所独有的,在定义构造函数时自动创建,它总是被 __proto__ 所指。所有对象都有__proto__属性,函数这个特殊对象除了具有__proto__属性,还有特有的原型属性prototype。prototype对象默认有两个属性,constructor属性和__proto__属性。prototype属性可以给函数和对象添加可共享(继承)的方法、属性,而__proto__是查找某函数或对象的原型链方式。constructor,这个属性包含了一个指针,指回原构造函数。


class继承

1.基本用法

传统方法

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

es6

class Point {
  constructor(x, y) {
    // constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加
    // this默认指向类的实例
    this.x = x;
    this.y = y;
  }
  static classMethod() {
  // 静态方法,可以直接在Point类上调用(Point.classMethod()),而不是在Point类的实例上调用
  // 这里的this指的是类,而不是实例
    return 'hello';
  }
  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
var point = new Point(2, 3);

point.toString() // (2, 3)
// x和y都是实例对象point自身的属性
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
// toString是原型对象的属性
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true

上面代码中,ES6语法中,toString方法是Point类内部定义的方法,它是不可枚举的。采用 ES5 的写法,toString方法就是可枚举的。

2.class的继承

class Point {
  constructor(x, y) {
    this.color = 'red';
    this.x = 1;
    console.log(x,y)
  }
  toString(){
    return 'Point + ' + this.color
}
}

class ColorPoint extends Point {
  constructor(x, y, color) {
    // super()在这里相当于ColorPoint.prototype.constructor.call(this,x,y)。
    super(x, y); // 调用父类的constructor(x, y)
    this.color = 'yellow';
    this.x = 2;
    super.x = 3;
    console.log(super.x); // undefined
    console.log(this.x); // 3
    // 由于this指向子类实例,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
    // 上面代码中,super.x赋值为3,这时等同于对this.x赋值为3。而当读取super.x的时候,读的是Point.prototype.x,所以返回undefined。
  }
  toString() {
    // 在这里调用super()会报错
    console.log('ColorPoint + ' + super.toString()) // ColorPoint +Point + yellow
  }
}
let a = new ColorPoint();
a.toString(); // ColorPoint + Point + yellow

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

  • 当super作为函数时:super虽然代表了父类Point的构造函数,但是返回的是子类ColorPoint的实例,即super内部的this指的是ColorPoint的实例,因此super()在这里相当于Point.prototype.constructor.call(this)。作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。
  • 当super作为对象时:在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

注意:当super作为对象时,由于super指向父类的原型对象,所以定义在父类
(constructor)实例上的方法或属性,是无法通过super调用的。

上面代码中,super.toString()虽然调用的是Point.prototype.toString(),但是Point.prototype.toString()内部的this指向子类ColorPoint的实例,导致输出的是yellow,而不是red。也就是说,实际上执行的是super.toString.call(this)

3.类的 prototype 属性和__proto__属性

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

  • 子类的proto属性,表示构造函数的继承,总是指向父类。

  • 子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性。

class A {
}

class B extends A {
}

B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true

相关文章

  • JavaScript笔记3

    RegExp、JSON、创建对象、构造函数、原型对象、原型链、原型继承、class、class继承 RegExp ...

  • JS如何实现继承

    使用原型链 class继承(extends、super)

  • 原型链和class继承

    从网上找了一张图,比较清楚的描述了原型链 原型链 1.原型链的定义 每个对象都可以有一个原型proto,这个原型还...

  • 类与继承

    目标 搞清楚原型链 知道组合寄生继承,知道 class 继承 知道怎么创建类 function / class 面...

  • JS基础知识体系

    JS基础知识 1、变量类型和计算 值类型和引用类型 类型判断 逻辑运算 2、原型和原型链 class 继承 原型 ...

  • class与原形链实现继承

    原型链继承:(寄生组合式继承) 在ES6的class语法推出之前,要实现类的继承要通过修改原型链来实现。 核心: ...

  • class继承,原型链

    1.构造函数,原型,实例之间的关系 每个构造函数都有一个原型对象(prototype属性),原型对象都包含一个指向...

  • JavaScript 原型、原型链与原型继承

    原型,原型链与原型继承 用自己的方式理解原型,原型链和原型继承 javascript——原型与原型链 JavaSc...

  • Class 的继承 extend继承 es6继承基本用法

    Class继承基本用法 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,...

  • JavaScript继承方式详解

    JavaScript实现继承的方式主要有两种: 原型链继承和借助构造函数继承 一、原型链继承 原型链继承的主要思想...

网友评论

      本文标题:原型链和class继承

      本文链接:https://www.haomeiwen.com/subject/gmsqkhtx.html