陌上人如玉
公子世无双

js的bind 和apply

JavaScript 中的 bindapply 是函数原型上的重要方法,二者核心作用都是改变函数执行时的 this 指向,但用法、执行时机和适用场景各有不同。今天就用通俗易懂的例子,帮大家理清它们的核心逻辑、实用场景,新手也能轻松理解和掌握~

一、前置核心认知

首先要明确一个前提:bindapply 都是 Function.prototype 上的方法,也就是说,所有函数都能直接调用这两个方法。它们的核心作用只有一个——改变函数执行时的 this 指向,但执行时机、参数传递方式和返回值完全不同。

二、apply 方法:改变this + 立即执行

1. 语法定义

function.apply(thisArg, [argsArray])

  • thisArg:函数执行时要绑定的 this 对象(如果传入基本类型,会自动转为对应的包装对象,比如传入数字1,会转为Number对象)。

  • [argsArray]:可选参数,是一个数组(或类数组对象),数组中的每一项会作为函数的参数,依次传入函数。

  • 核心特点:调用 apply 后,函数会立即执行,返回值是函数执行的结果。

2. 基础示例:改变this指向

最直观的用法,就是改变函数原本的 this 指向,让函数在指定对象的作用域内执行。

// 定义一个对象

const person = {

name: "张三",

age: 20

};

// 定义一个普通函数,默认this指向全局(浏览器中是window,Node中是global)

function sayHello(like, hobby) {

console.log(`我是${this.name},年龄${this.age},喜欢${like},爱好${hobby}`);

}

// 直接调用:this指向全局,name和age都是undefined

sayHello("吃火锅", "打篮球"); 

// 输出:我是undefined,年龄undefined,喜欢吃火锅,爱好打篮球

// 使用apply改变this指向,绑定到person对象,且立即执行

sayHello.apply(person, ["吃火锅", "打篮球"]); 

// 输出:我是张三,年龄20,喜欢吃火锅,爱好打篮球

3. 实用场景:处理数组参数

apply的一个经典用法,是解决一些不支持数组参数的函数(比如 Math.max()Math.min())的参数传递问题,无需手动遍历数组,简洁高效。

// 需求:求数组中的最大值

const numbers = [1, 9, 5, 12, 3];

// Math.max() 本身只支持单个参数传入,不支持数组

// 错误用法:Math.max(numbers) → NaN

// 正确用法:用apply将数组转为参数列表,thisArg传null(非严格模式下,null/undefined会指向全局)

const maxNum = Math.max.apply(null, numbers); 

console.log(maxNum); // 输出:12

// 补充:ES6之后可以用扩展运算符 ... 替代,效果一致

const maxNum2 = Math.max(...numbers); // 输出:12

三、bind 方法:改变this + 延迟执行

1. 语法定义

function.bind(thisArg[, arg1[, arg2[, ...]]])

  • thisArg:和apply一样,是函数执行时要绑定的 this 对象。

  • arg1, arg2...:可选参数,是提前传入的函数参数(也就是“函数柯里化”的简单实现)。

  • 核心特点:调用 bind 后,不会立即执行函数,而是返回一个绑定了this指向的新函数,后续需要手动调用这个新函数,才能执行原函数的逻辑。

2. 基础示例:绑定this,延迟执行

对比apply的立即执行,bind的延迟执行特性,适合需要复用绑定后函数的场景。

const person = {

name: "李四",

age: 25

};

function sayHi(like, hobby) {

console.log(`我是${this.name},年龄${this.age},喜欢${like},爱好${hobby}`);

}

// 使用bind绑定this到person,返回新函数(不执行)

const bindSayHi = sayHi.bind(person, "喝奶茶");

// 手动调用新函数,传入剩余的参数

bindSayHi("打游戏"); 

// 输出:我是李四,年龄25,喜欢喝奶茶,爱好打游戏

3. 实用场景:解决回调函数this丢失

在日常开发中,经常会遇到回调函数this丢失的问题,比如定时器、事件监听的回调函数,默认this会指向全局(window),导致无法访问目标对象的属性,用bind就能完美解决。

const user = {

name: "王五",

getInfo: function() {

// 定时器回调的this,默认指向window(非严格模式)

setTimeout(function() {

console.log(`用户名:${this.name}`); // 若不绑定this,输出undefined

}.bind(this), 1000); // 绑定this为当前的user对象(getInfo中的this就是user)

}

};

user.getInfo(); // 1秒后输出:用户名:王五

补充:ES6的箭头函数也能解决this丢失问题,但bind的优势在于可以复用绑定后的函数,灵活性更高。

四、bind vs apply 核心对比

为了更清晰地区分两者的差异,用表格总结核心特性,方便大家对比学习和记忆:

核心差异对比:

  • 执行时机:apply 立即执行函数;bind 不立即执行,返回绑定好this的新函数,需手动调用。

  • 参数传递:apply 的第二个参数是数组/类数组,一次性传入所有参数;bind 的第二个及以后参数逐个传入,也可在调用新函数时补充参数。

  • 返回值:apply 返回函数执行的结果;bind 返回绑定了this指向的新函数。

  • 适用场景:apply 适合参数是数组、需要立即执行函数的场景(如求数组最值);bind 适合回调函数this丢失、需要复用绑定后函数的场景(如定时器、事件回调)。

五、学习总结

  1. 核心共性:bindapply 都能改变函数执行时的 this 指向,本质是修改函数的执行上下文,让函数能在指定的作用域内执行。

  2. 关键区别:核心差异在于执行时机、参数传递方式和返回值(记住“apply立即执行传数组,bind延迟执行传单个”,能快速区分两者)。

  3. 易错点:bind返回的是新函数,必须手动调用才会执行;apply的第二个参数必须是数组(或类数组),否则会报错。

掌握这两个方法的核心逻辑和实用场景,能帮我们更灵活地处理函数执行上下文,提升代码的可读性和灵活性,为后续学习更复杂的JS知识点打下基础~

赞(0) 打赏
未经允许不得转载:陌上寒 » js的bind 和apply

评论 抢沙发

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

微信扫一扫

支付宝扫一扫