面试之《原型与原型链》

在 JavaScript 中,原型(Prototype)原型链(Prototype Chain) 是实现对象继承和属性共享的核心机制。以下是详细介绍:

一、原型(Prototype)

  1. 基本概念

    • 每个函数(包括构造函数)都有一个 prototype 属性,指向一个对象,称为原型对象
    • 当使用 new 调用构造函数创建实例时,实例内部会有一个隐藏属性 __proto__(ES6 规范中称为 [[Prototype]]),指向构造函数的原型对象。
    • 原型对象的作用是为所有实例共享属性和方法,避免重复定义。
  2. 示例

    javascript 复制代码
    function Person(name) {
      this.name = name;
    }
    
    // 原型对象添加方法
    Person.prototype.sayHello = function() {
      console.log(`Hello, ${this.name}`);
    };
    
    const person = new Person("Alice");
    console.log(person.__proto__ === Person.prototype); // true
    person.sayHello(); // Hello, Alice

二、原型链(Prototype Chain)

  1. 基本概念

    • 每个对象(包括原型对象)都有自己的 __proto__,指向其"父级"原型对象,形成一条链式结构,称为原型链
    • 当访问对象的属性或方法时,JavaScript 会沿着原型链向上查找,直到找到目标属性或到达 null(终点)。
  2. 原型链结构

    复制代码
    Object.prototype ← Function.prototype ← ... ← 自定义原型 ← 实例
    • 所有对象的最终原型是 Object.prototype,它定义了 toString()valueOf() 等通用方法。
    • 函数的原型是 Function.prototype,而 Function.prototype 的原型是 Object.prototype
  3. 示例

    javascript 复制代码
    const obj = {};
    console.log(obj.toString()); // 来自 Object.prototype
    console.log(obj.hasOwnProperty("toString")); // false(属于原型链)

三、关键特性

  1. 属性查找规则

    • 优先查找对象自身的属性,若不存在则沿原型链向上查找。
    • 修改对象自身的属性会直接覆盖原型链中的同名属性。
  2. 原型链的继承

    • 通过修改原型对象,可以实现类似"继承"的效果。例如:

      javascript 复制代码
      function Animal() {}
      Animal.prototype.eat = function() { console.log("Eating..."); };
      
      function Dog() {}
      Dog.prototype = Object.create(Animal.prototype); // Dog 的原型链继承 Animal
      Dog.prototype.bark = function() { console.log("Woof!"); };
      
      const dog = new Dog();
      dog.eat(); // 继承自动物原型
      dog.bark(); // 自身方法
  3. 原型链的终点

    • Object.prototype.__proto__ 的值为 null,表示原型链的结束。

四、相关方法

  1. isPrototypeOf()

    检查一个对象是否是另一个对象的原型:

    javascript 复制代码
    console.log(Animal.prototype.isPrototypeOf(dog)); // true
  2. hasOwnProperty()

    判断属性是否是对象自身的属性(而非原型链中的属性):

    javascript 复制代码
    console.log(dog.hasOwnProperty("bark")); // true
  3. Object.getPrototypeOf()

    获取对象的原型(ES6 方法,替代 __proto__):

    javascript 复制代码
    console.log(Object.getPrototypeOf(dog) === Dog.prototype); // true

五、注意事项

  • 避免原型链过长:过长的原型链会影响属性查找性能。
  • 原型与实例的动态关联:修改原型对象会影响所有后续创建的实例,但已存在的实例不会受影响。
  • class 语法糖 :ES6 的 class 本质上仍基于原型链,只是语法糖简化了实现。

总结

  • 原型是对象共享属性和方法的基础。
  • 原型链 通过 __proto__ 连接对象,实现属性的继承和查找。
  • 理解原型链有助于掌握 JavaScript 的核心机制(如继承、多态),并避免常见错误。
相关推荐
中微子6 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102421 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
趣多多代言人22 分钟前
从零开始手写嵌入式实时操作系统
开发语言·arm开发·单片机·嵌入式硬件·面试·职场和发展·嵌入式
芬兰y36 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁43 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry43 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录1 小时前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟1 小时前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构