MST

星途 面试题库

面试题:JavaScript 中 call、apply、bind 在复杂继承场景下的深度剖析

在 JavaScript 基于原型链的复杂继承场景中,call、apply 和 bind 方法会对继承关系、实例化对象的属性和方法产生不同的影响,请深入分析这些影响,并通过代码示例展示如何利用它们优化继承结构和实现特定的功能。
27.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

1. call、apply 和 bind 方法简介

  • call:调用一个函数,其第一个参数作为函数内部 this 的值,后面的参数作为函数的参数依次传入。
  • apply:与 call 类似,但第二个参数是一个数组,数组中的元素作为函数的参数传入。
  • bind:创建一个新的函数,将原函数的 this 绑定到指定的值,返回的新函数可以稍后调用,调用时传入的参数作为新函数的参数。

2. 对继承关系、实例化对象属性和方法的影响

对继承关系的影响

  • call 和 apply:可以在子类构造函数中调用父类构造函数,通过 callapply 将父类构造函数中的 this 指向子类实例,从而让子类实例能够继承父类的属性。例如:
function Animal(name) {
    this.name = name;
}
function Dog(name, breed) {
    Animal.call(this, name);
    this.breed = breed;
}

这里 Dog 构造函数通过 call 调用 Animal 构造函数,使得 Dog 实例拥有了 Animal 构造函数定义的 name 属性。

  • bind:通常不直接用于影响继承关系,但可以用于创建一个预先绑定 this 的函数,在继承结构中可能间接用于特定功能。例如,在子类方法中如果需要使用父类方法且保持特定 this 指向时可以用到。

对实例化对象属性和方法的影响

  • call 和 apply:调用函数时改变函数内部 this 的指向,从而影响实例化对象属性的访问和修改。例如:
function Person() {
    this.age = 0;
    this.growUp = function (years) {
        this.age += years;
    };
}
function Employee() {
    Person.call(this);
}
let emp = new Employee();
emp.growUp.apply(emp, [5]);
console.log(emp.age); 

这里通过 apply 调用 growUp 方法,this 指向 emp,从而正确修改了 empage 属性。

  • bind:返回一个新函数,新函数的 this 已经被绑定,不会在调用时改变。例如:
function greet() {
    console.log(`Hello, I'm ${this.name}`);
}
let person = { name: 'John' };
let boundGreet = greet.bind(person);
boundGreet(); 

这里 boundGreet 函数的 this 始终绑定为 person,无论在何处调用。

3. 利用它们优化继承结构和实现特定功能

优化继承结构

通过 callapply 在子类构造函数中调用父类构造函数是一种常见的优化继承结构的方式,确保子类实例拥有父类的属性。例如:

function Shape(color) {
    this.color = color;
}
Shape.prototype.getColor = function () {
    return this.color;
};
function Rectangle(width, height, color) {
    Shape.call(this, color);
    this.width = width;
    this.height = height;
}
Rectangle.prototype.getArea = function () {
    return this.width * this.height;
};
let rect = new Rectangle(5, 10, 'blue');
console.log(rect.getColor()); 
console.log(rect.getArea()); 

这里 Rectangle 子类通过 call 调用 Shape 父类构造函数,优化了继承结构,使得 Rectangle 实例既拥有父类的 color 属性和 getColor 方法,又有自己特有的 widthheight 属性和 getArea 方法。

实现特定功能

  • bind 实现事件处理函数的特定 this 绑定:在 DOM 事件处理中,this 通常指向触发事件的 DOM 元素。如果希望在事件处理函数中使用特定对象的属性和方法,可以使用 bind。例如:
<button id="btn">Click me</button>
<script>
    function ButtonHandler() {
        this.message = 'Button clicked!';
        this.handleClick = function () {
            console.log(this.message);
        };
    }
    let handler = new ButtonHandler();
    document.getElementById('btn').addEventListener('click', handler.handleClick.bind(handler));
</script>

这里通过 bindhandler.handleClick 函数的 this 绑定为 handler,确保在事件处理时能正确访问 handlermessage 属性。