JS - 原型及原型链

new 操作符

先让我们看一段简单的代码:

function Test() {
    this.a = "a";
}
Test.prototype.getThis = function() {
    console.log(this);
};

const test = new Test();
test.getThis(); // { a: "a", __proto__: Test.prototype }

new 操作符做了什么?

引用 MDN 的说法:

  1. 创建一个空白且简单的对象

    通过 new Object(null) 创建一个空白对象 {}

  2. 链接该对象到另一个对象

    为步骤 1 创建的对象添加 __proto__ 属性指向函数原型 ( Test.prototype ).
    得到 { __proto__: Test.prototype }

  3. 将步骤 1 创建的对象作为 this

    this = { __proto__: Test.prototype }

    执行 Test 的 constructor 函数, 最终 this = { a: 'a', __proto__: Test.prototype }

  4. 如果该函数没有返回 对象, 则返回 this, 否则返回 对象

prototype

prototype 中文名叫做原型

重点:只有函数拥有原型

函数原型的好处: 当通过 new 操作符创建新对象时, 如果没有原型, 那么我们把所有属性都挂载到实例上, 每一个实例都这样做是浪费内存的

而有了原型, 我们就可以通过引用原型的方式共享属性(共享的属性一般为函数方法)

通过前面我们知道 test = { a: 'a', __proto__: Test.prototype }

test 中虽然没有 getThis 方法, 但是仍然可以调用 getThis , 这里面就是原型链起作用了

__proto__

Chrome 用 __proto__ 实现原型链, 所有对象均存在 __proto__ 属性(null 不是对象, null 没有 __proto__ 属性)

当读取实例的属性时, 如果找不到, 就会查找与对象关联的原型中的属性, 如果还查不到, 就去找原型的原型, 一直找到最顶层为止 JavaScript 深入之从原型到原型链

分析上面的例子, 因为 test 中没有 getThis 方法, 所以去查找 test.__proto__.getThis , 即 Test.prototype.getThis

那如果我们调用 test.hasOwnProperty 又是怎样的呢?

首先, 在 const test = new Test() 过程中, 创建以下关系:

之前提到, 所有对象均存在 __proto__ 属性, 所以 Test.prototype 也存在 __proto__ 属性, 那么这个值是什么?

答案很简单, Test.prototype 是个对象, 所以 Test.prototype.__proto__ = Object.prototype .

更新关系图如下:

Object.__proto__ = null , 所以完整原型链如下:

补充

函数原型创建时有 constructor 属性指向函数本身, 即:

function Test() {}
Test.prototype.constructor === Test; // true

JS 里面的 Class 本身就是函数的语法糖, 不再需要修改函数的 prototype 属性来共享方法, extends 实际上就是修改了原型的 __proto__ 属性

class Test1 {
    a = "a";
    constructor() {
        this.b = "b";
    }
    getC() {
        console.log(this.c);
    }
}

class Test2 extends Test1 {
    constructor() {
        super();
        this.c = "c";
    }

    getAB() {
        console.log(this.a, this.b);
    }
}

const test = new Test2();
test.getAB();
test.getC();

写成函数形式:

function Test1() {
    this.a = "a";
    this.b = "b";
}
Test1.prototype.getC = function() {
    console.log(this.c);
};

function Test2() {
    Test1.call(this);
    this.c = "c";
}
Test2.prototype.getAB = function() {
    console.log(this.a, this.b);
};
Reflect.setPrototypeOf(Test2.prototype, Test1.prototype);

const test = new Test2();
test.getAB();
test.getC();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值