前端开发面试题—JavaScript原型链

📚文章目录

🔗面试题:什么是原型链?

🔗原型链的结构总结


在JavaScript面向对象中,原型链是一个很重要的知识点,经常出现在大大小小的面试题中,关于原型链的面试题有很多问法和知识点。今天主要分享一下我遇到的一个关于原型链的面试题。问题很简单,什么是原型链?(⊙_⊙;)

🔗面试题:什么是原型链?

说到原型链,就不得不先说说什么是原型对象了,这里先简单介绍一下原型对象

  • 在JavaScript中,每个构造函数都有一个原型对象存在,这个原型对象通过构造函数的prototype属性来访问
  • 利用原型对象,可以实现为所有的实例对象共享实例方法,不仅节省了内存,还体现了实例对象之间的联系。我们可以将实例方法定义在原型对象中,然后所有的实例方法就都可以访问原型对象的方法了。因此,原型对象其实就是所有实例对象的原型

简单用代码演示一下

 接下来回归主题,介绍原型链

  • 当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(__proto__),层层向上直到一个对象的原型对象为 null 。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例

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

代码演示

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>
        // 让我们从一个函数里创建一个对象 o,它自身拥有属性 a 和 b 的:
        let f = function () {
            this.a = 1;
            this.b = 2;
        }
        /* 这么写也一样
        function f() {
          this.a = 1;
          this.b = 2;
        }
        */
        let o = new f(); // {a: 1, b: 2}

        // 在 f 函数的原型上定义属性
        f.prototype.b = 3;
        f.prototype.c = 4;

        // 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
        // o.[[Prototype]] 有属性 b 和 c
        //  (其实就是 o.__proto__ 或者 o.constructor.prototype)
        // o.[[Prototype]].[[Prototype]] 是 Object.prototype.
        // 最后 o.[[Prototype]].[[Prototype]].[[Prototype]] 是 null
        // 这就是原型链的末尾,即 null,
        // 根据定义,null 就是没有 [[Prototype]]。

        // 综上,整个原型链如下:

        // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null

        console.log(o.a); // 1
        // a 是 o 的自身属性吗?是的,该属性的值为 1

        console.log(o.b); // 2
        // b 是 o 的自身属性吗?是的,该属性的值为 2
        // 原型上也有一个'b'属性,但是它不会被访问到。
        // 这种情况被称为"属性遮蔽 (property shadowing)"

        console.log(o.c); // 4
        // c 是 o 的自身属性吗?不是,那看看它的原型上有没有
        // c 是 o.[[Prototype]] 的属性吗?是的,该属性的值为 4

        console.log(o.d); // undefined
        // d 是 o 的自身属性吗?不是,那看看它的原型上有没有
        // d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
        // o.[[Prototype]].[[Prototype]] 为 null,停止搜索
        // 找不到 d 属性,返回 undefined
    </script>

</body>

<script>

</script>

</html>
  • 简单概括一下,在JavaScript中,对象有原型对象,原型对象也有原型对象,这样就形成了一个链式结构,称为原型链

 参考来自🔽

MDN 继承与原型链

🔗原型链的结构总结

总结为以下4点:

① 每个构造函数都有一个prototype属性指向原型对象。

  • function Person() {}          // 定义函数
    
    console.log(Person.prototype);     // 输出结果:{constructor: ƒ}
    
    console.log(typeof Person.prototype);  // 输出结果:object

② 原型对象通过constructor属性指向构造函数。

  • function Person() {}
    
    // 通过原型对象访问构造函数
    
    console.log(Person.prototype.constructor === Person);  // 输出结果:true
    
    // 通过实例对象访问构造函数
    
    var p1 = new Person();
    
    console.log(p1.constructor === Person);       // 输出结果:true

③ 通过实例对象的__proto__属性可以访问原型对象。

  • function Person() {}
    
    var p1 = new Person();
    
    console.log(p1.__proto__ === Person.prototype); // 输出结果:true

④ Object的原型对象的__proto__属性为null。  

  • console.log(Object.prototype.__proto__);  // 输出结果:null

根据以上4点,绘制原型链的结构图如下

最后祝大家面试遇到原型链的问题都能完美答回答🎉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黛琳ghz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值