深入解析JavaScript原型链面试题

JavaScript 是一种弱类型、基于原型的编程语言。原型是 JavaScript 的一项非常重要的特性,也是面试中经常考察的知识点。JS 原型链是基于原型的面向对象编程的基石,掌握这一知识点对于我们理解 JavaScript 的对象模型非常重要。本文将带你从多个方面深入剖析JavaScript原型链面试题。

一、JS原型链基本概念

在 JavaScript 中,每个函数都有一个 prototype 属性,也就是原型对象。原型对象是一个普通的对象,包含属性和方法。每个实例对象都通过 __proto__ 属性引用其构造函数的原型对象 prototype。

function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype.sayHello = function() {
  console.log(`Hello, I'm ${this.name}, I'm ${this.age} years old.`);
}
const person = new Person('Tom', 18);

在以上代码中,Person 函数有一个 prototype 属性,它是一个普通的对象,并且包含一个方法 sayHello。person 是使用 Person 函数构造出来的实例对象, 它通过 __proto__ 属性引用了 Person 的原型对象 Person.prototype,因此它可以使用原型对象中的方法 sayHello。

二、JS原型链的构建方式

原型链是由每个对象的 __proto__ 属性构成的。我们可以通过以下方式构建原型链:

1. 新建一个构造器函数

2. 扩展构造器的原型对象

3. 使用 new 操作符创建子对象

4. 构造器原型对象的 __proto__ 属性指向构造器父级的原型对象

5. 子对象的 __proto__ 属性指向了构造器的原型对象,也就是形成了原型链

function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function () {
  console.log(this.name);
}

function Dog(name, age) {
  this.age = age;
  Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype); // Dog 继承 Animal 
Dog.prototype.constructor = Dog; // constructor 指向 Dog 
Dog.prototype.sayAge = function () {
  console.log(this.age);
}

const dog = new Dog('Lily', 1);

在以上代码中,Dog 继承了 Animal 的方法以及属性。通过 Dog.prototype = Object.create(Animal.prototype),Dog 的原型指向了 Animal 的原型,因此它可以使用 Animal 的原型中的方法 sayName,在 Dog 的原型中添加 sayAge 方法。

三、JS原型链的查找顺序

当我们在一个实例对象上调用一个属性或者方法时,JavaScript 引擎会按照如下的顺序查找属性或方法:

1. 首先查找实例对象本身是否有该属性或方法

2. 如果没有,则查找实例对象的原型对象是否有该属性或方法

3. 如果还没有,则查找实例对象原型对象的原型对象是否有该属性或方法

4. 重复上述步骤,直到查找到 Object 的原型对象,即可结束查找

function Animal(name) {
  this.name = name;
}
Animal.prototype.sayName = function () {
  console.log(this.name);
}

function Dog(name, age) {
  this.age = age;
  Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.sayAge = function () {
  console.log(this.age);
}

const dog = new Dog('Lily', 1);
console.log(dog.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
console.log(Animal.prototype.__proto__ === Object.prototype); // true

在以上代码中,dog 是 Dog 的实例对象。当我们在 dog 上调用 sayAge 方法时,首先查找 dog 本身是否有该方法,发现没有。然后查找 Dog.prototype 是否有该方法,发现有。因此调用了该方法并输出了 dog 的年龄。在这个查找的过程中,JS 引擎按照 __proto__ 属性指向的原型对象继续查找,直到最后找到 Object 的原型对象 Object.prototype 为止。

四、JS原型链的继承方式

在 JavaScript 中,有很多实现继承的方法。下面分别介绍一下常用的几种继承方式:

1. 构造函数继承

构造函数继承是一种常用的继承方式。其基本思想是在子类的构造函数中调用父类的构造函数。

function Parent(age) {
  this.age = age;
}
function Child(age) {
  Parent.call(this, age);
}
const child = new Child(18);
console.log(child.age); // 18

在以上代码中,Child 函数的构造函数中调用了 Parent 的构造函数并传入参数。Child 实例可以访问到 Parent 实例中的属性 age。

2. 原型链继承

原型链继承的基本思想是通过将子类的原型对象指向父类的实例对象来实现继承。

function Parent(age) {
  this.age = age;
}
Parent.prototype.sayAge = function () {
  console.log(this.age);
};
function Child(age) {}
Child.prototype = new Parent(18);
const child = new Child();
console.log(child.age); // 18
child.sayAge(); // 18

以上代码中,Child 的原型指向了 Parent 的实例,并且 Child 的实例可以访问到 Parent 中的方法和属性。

3. 组合继承

组合继承是上述两种继承方式的结合。其基本思想是通过构造函数继承实现属性的继承,通过原型链继承实现方法的继承。

function Parent(age) {
  this.age = age;
}
Parent.prototype.sayAge = function () {
  console.log(this.age);
};
function Child(age) {
  Parent.call(this, age);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
const child = new Child(18);
console.log(child.age); // 18
child.sayAge(); // 18

以上代码中,Child 函数的构造函数中调用了 Parent 的构造函数并传入参数,实现了属性的继承。Child 的原型对象指向了 Parent 的原型对象,并且将 constructor 指向了 Child 函数,实现了方法的继承。

结语

JavaScript 原型链是一种非常重要的特性。理解原型链能够帮助我们更好地理解 JavaScript 的对象模型和继承机制。掌握 JavaScript 原型链的实现方式以及查找顺序可以帮助我们更好地回答面试题。在实际项目中,可以根据练习的需求选择不同的继承方式以实现需求。

原创文章,作者:XGIKP,如若转载,请注明出处:https://www.506064.com/n/363902.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
XGIKPXGIKP
上一篇 2025-03-12 18:48
下一篇 2025-03-12 18:48

相关推荐

  • 使用JavaScript日期函数掌握时间

    在本文中,我们将深入探讨JavaScript日期函数,并且从多个视角介绍其应用方法和重要性。 一、日期的基本表示与获取 在JavaScript中,使用Date对象来表示日期和时间,…

    编程 2025-04-28
  • JavaScript中使用new Date转换为YYYYMMDD格式

    在JavaScript中,我们通常会使用Date对象来表示日期和时间。当我们需要在网站上显示日期时,很多情况下需要将Date对象转换成YYYYMMDD格式的字符串。下面我们来详细了…

    编程 2025-04-27
  • 源码审计面试题用法介绍

    在进行源码审计面试时,可能会遇到各种类型的问题,本文将以实例为基础,从多个方面对源码审计面试题进行详细阐述。 一、SQL注入 SQL注入是常见的一种攻击方式,攻击者通过在输入的参数…

    编程 2025-04-27
  • JavaScript中修改style属性的方法和技巧

    一、基本概念和方法 style属性是JavaScript中一个非常重要的属性,它可以用来控制HTML元素的样式,包括颜色、大小、字体等等。这里介绍一些常用的方法: 1、通过Java…

    编程 2025-04-25
  • 深入解析Vue3 defineExpose

    Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但…

    编程 2025-04-25
  • CloneDeep函数在Javascript开发中的应用

    一、CloneDeep的概念 CloneDeep函数在Javascript中是一种深层克隆对象的方法,可以在拷贝对象时避免出现引用关系。使用者可以在函数中设置可选参数使其满足多种拷…

    编程 2025-04-25
  • JavaScript中的Object.getOwnPropertyDescriptors()

    一、简介 Object.getOwnPropertyDescriptors()是JavaScript中一个非常有用的工具。简单来说,这个方法可以获取一个对象上所有自有属性的属性描述…

    编程 2025-04-25
  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25

发表回复

登录后才能评论