#

基类:没有使用 extends 关键字的类声明被称作基类。

如果你的派生类需要引用它的父类,可以使用 super 关键字。

委托:在另一个对象上查找不存在属性的过程称作委托。

静态方法:是构造方法自己的方法,不能被类的实例化对象调用。我们使用 static 关键字定义静态方法。

// FatFreeFood 是一个派生类
class FatFreeFood extends Food {

    constructor (name, protein, carbs) {
        super(name, protein, carbs, 0);
    }

    print () {
        super.print();
        console.log(`Would you look at that -- ${this.name} has no fat!`);
    }

}

在 JavaScript 中仅有两个 super 关键字的使用场景:

  1. 在子类构造函数中调用。如果初始化派生类是需要使用父类的构造函数,我们可以在子类的构造函数中调用 super(parentConstructorParams),传递任意需要的参数。
  2. 引用父类的方法。在常规方法定义中,派生类可以使用点运算符来引用父类的方法:super.methodName。

# 原型链

每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

**JavaScript 对象是动态的属性“包”(指其自己的属性)。**JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

构造函数的 prototype 属性,为其生成的实例 原型 指针。与其实例 __proto__

# 关于原型的要点

  1. 所有的函数都有一个属性,叫做 .prototype,它指向这个函数的关联对象。
  2. 所有函数的原型都有一个属性,叫做 .constructor,它指向这个函数本身。
  3. 一个函数原型的 .constructor 并非必须指向创建这个函数原型的函数……有点绕,我们等下会深入探讨一下。

# create 设置原型

还记得使用 new 调用函数的时候,JavaScript 在幕后干了哪四件事儿吗?Object.create 就干了这三件事儿:

  1. 创建一个新对象;
  2. 设置它的原型引用;
  3. 返回这个新对象。
"use strict";

const foo = {
    speak () {
        console.log('Foo!');
    }
};

const bar = Object.create(foo);

bar.speak(); // 'Foo!'
Object.getPrototypeOf(bar) === foo; // true

# 强行 new 构造调用

"use strict";

// 强行构造调用
function Food (name, protein, carbs, fat) {
    // 如果用户忘了手工调用一下
    if (!new.target)
        return new Food(name, protein, carbs, fat);

    this.name    = name;
    this.protein = protein;
    this.carbs   = carbs;
    this.fat     = fat;
}

const fish = Food('Halibut', 26, 0, 2); // 糟了,不过没关系!
fish; // 'Food {name: "Halibut", protein: 20, carbs: 5, fat: 0}'
"use strict";

function Food (name, protein, carbs, fat) {

    if (!(this instanceof Food))
        return new Food(name, protein, carbs, fat);

    this.name    = name;
    this.protein = protein;
    this.carbs   = carbs;
    this.fat     = fat;
}

# 参考

(opens new window) 【进阶5-1期】重新认识构造函数、原型和原型链 (opens new window)

Last Updated: 5/14/2022, 11:38:45 AM