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


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

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

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

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

    简单用代码演示一下

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

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

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

    代码演示

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
    6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    7. <title>Documenttitle>
    8. head>
    9. <body>
    10. <script>
    11. // 让我们从一个函数里创建一个对象 o,它自身拥有属性 a 和 b 的:
    12. let f = function () {
    13. this.a = 1;
    14. this.b = 2;
    15. }
    16. /* 这么写也一样
    17. function f() {
    18. this.a = 1;
    19. this.b = 2;
    20. }
    21. */
    22. let o = new f(); // {a: 1, b: 2}
    23. // 在 f 函数的原型上定义属性
    24. f.prototype.b = 3;
    25. f.prototype.c = 4;
    26. // 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
    27. // o.[[Prototype]] 有属性 b 和 c
    28. // (其实就是 o.__proto__ 或者 o.constructor.prototype)
    29. // o.[[Prototype]].[[Prototype]] 是 Object.prototype.
    30. // 最后 o.[[Prototype]].[[Prototype]].[[Prototype]] 是 null
    31. // 这就是原型链的末尾,即 null,
    32. // 根据定义,null 就是没有 [[Prototype]]。
    33. // 综上,整个原型链如下:
    34. // {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
    35. console.log(o.a); // 1
    36. // a 是 o 的自身属性吗?是的,该属性的值为 1
    37. console.log(o.b); // 2
    38. // b 是 o 的自身属性吗?是的,该属性的值为 2
    39. // 原型上也有一个'b'属性,但是它不会被访问到。
    40. // 这种情况被称为"属性遮蔽 (property shadowing)"
    41. console.log(o.c); // 4
    42. // c 是 o 的自身属性吗?不是,那看看它的原型上有没有
    43. // c 是 o.[[Prototype]] 的属性吗?是的,该属性的值为 4
    44. console.log(o.d); // undefined
    45. // d 是 o 的自身属性吗?不是,那看看它的原型上有没有
    46. // d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
    47. // o.[[Prototype]].[[Prototype]] 为 null,停止搜索
    48. // 找不到 d 属性,返回 undefined
    49. script>
    50. body>
    51. <script>
    52. script>
    53. html>
    • 简单概括一下,在JavaScript中,对象有原型对象,原型对象也有原型对象,这样就形成了一个链式结构,称为原型链

     参考来自🔽

    MDN 继承与原型链

    🔗原型链的结构总结

    总结为以下4点:

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

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    机试打卡 -05 接雨水(动态规划&栈)
    JDBC中setTransactionIsolation
    RabbitMQ 学习(一)-- 概念和安装
    5分钟实现「视频检索」:基于内容理解,无需任何标签
    1、MongoDb综述
    【AGC】崩溃服务之常见问题
    图像分割 人脸分割CVPR2023笔记
    且看五年开发码农,如何备战仨月硬刚字节面试官,轻松拿offer
    工程化面试题
    QTableWidget相关操作
  • 原文地址:https://blog.csdn.net/weixin_53231455/article/details/126239468