4.js中原型链是什么

52 阅读2分钟

原型链是什么?

假设我们有一个普通对象 x={},这个 x 会有一个隐藏属性,叫做 __?????__ ,这个属性会指向 Object.prototype ,即

    x.__?????__ === Object.prototype // 原型

此时,我们说 x 的原型 是 Object.prototype,或者说 Object.prototype 是 x 的原型。 而这个 __?????__ 属性的唯一作用就是用来指向 x 的原型的。 如果没有 __?????__ 属性,x 就不知道自己的原型是谁了。

为什么我用问号来表示?因为这样你不容易晕。

接下来我来说说原型链,我还是举例说明吧。 假设我们有一个数组对象 a=[] ,这个 a 也会有一个隐藏属性,叫做 __?????__ ,这个属性会指向 Array.prototype ,即

    a.__?????__ === Array.prototype

此时,我们说 a 的原型是 Array.prototype,跟上面的 x 一样。但又有一点不一样,那就是 Array.prototype 也有一个隐藏属性 __?????__ ,指向 Object.prototype ,即

    // 用 x 表示 Array.prototype
    x.__?????__ === Object.prototype

这样一来,a 就有两层原型:

  1. a 的原型是 Array.prototype
  2. a 的原型的原型是 Object.prototype

于是就通过隐藏属性 __?????__ 形成了一个链条:

    a ===> Array.prototype ===> Object.prototype 

这就是原型链。

举例子a = [] b = Array.prototype c = Object.prototype

a的原型是b,b的原型是c,abc组成了一个原型链

    a.__?????__= b 
    b.__?????__= c

如何创建新的原型链?

怎么做:

看起来只要改写 x 的隐藏属性 __?????__ 就可以改变 x 的原型(链)

    x.__?????__ = 原型

但是这不是标准推荐的写法,为了设置 x.__?????___,推荐的写法是

    const x = Object.create(原型)
    // 或
    const x = new 构造函数() // 会导致 x.__?????__ === 构造函数.prototype

也就是说

    a.__?__ === f // 不能直接这么写
    a = Object.create(f) // es6,要这么写
    a = new cf() // es5,要么这么写, a.__?__ === cf.prtotype

解决了什么问题?

在没有 Class 的情况下实现「继承」。以 a ===> Array.prototype ===> Object.prototype 为例,我们说:

  1. a 是 Array 的实例,a 拥有 Array.prototype 里的属性
  2. Array 继承了 Object(注意专业术语的使用)
  3. a 是 Object 的间接实例,a 拥有 Object.prototype 里的属性 这样一来,a 就既拥有 Array.prototype 里的属性,又拥有 Object.prototype 里的属性。

优点: 简单、优雅。

缺点: 跟 class 相比,不支持私有属性。

怎么解决缺点: 使用 class 呗。但 class 是 ES6 引入的,不被旧 IE 浏览器支持。

    class F {
        #scope = 'f'
    }
    a = new F()
    a.scope
    console.dir(a)