本文详解JavaScript中call、apply和bind三个核心函数的用法与区别。三者均可改变函数内部的this指向,但call和apply会立即执行函数,而bind返回新函数不立即执行。主要区别在于参数传递形式:call接受参数列表,apply接受数组。call常用于继承,apply常用于数组最大值计算,bind常用于定时器或事件处理中绑定this。
call()函数详解
基本介绍
call方法的核心作用是通过指定一个新的this值来调用当前函数或方法,从而改变函数执行时的上下文环境。
语法结构
fn.call(this.Arg, arg1, arg2,...)
参数说明:thisArg为调用函数时指定的this对象;arg1, arg2等为后续传递的参数,若直接传给形参可省略部分参数。
主要特点
- 能够直接调用函数,例如
fn.call()。 - 可以改变被调用函数的this指向为指定的对象,例如
fn.call(this.Arg)。
返回值说明
调用者提供的值和参数调用该函数的返回值,即原函数的返回值。若该方法没有返回值,则返回undefined。
主要应用场景
常用于通过call()来实现构造函数之间的继承。
// 借用父构造函数继承属性
// 父构造函数
function Father(name, age) {
this.uname = name
this.age = age
}
// 子构造函数
function Son(name, age) {
Father.call(this, name, age)
}
var son = new Son('小明', 10)
console.log(son); // Son {uname: '小明', age: 10}
apply()函数详解
基本介绍
apply意为应用。该方法用于调用一个具有指定this值的函数,并接收一个数组(或类数组对象)作为参数列表this。简而言之,它是调用函数的一种方式,同时具备改变this指向的功能。
语法结构
fn.apply(this.Arg, [argsArray])
参数说明:thisArg为函数运行时指定的this值,若无需改变this指向可填null;argsArray为传递的值,必须包含在数组中。
主要特点
- 同样用于调用函数,例如
fn.apply()。 - 可以改变函数内部的this指向,例如
fn.apply(this),但其参数必须以数组(或伪数组)形式传递。
返回值说明
apply()的返回值即为被调用函数的返回值,因为它直接执行了函数调用。若该方法没有返回值,则返回undefined。
主要应用场景
var a = {
name: '小红'
}
function fn(arr) {
console.log(this); // {name: '小红'}
console.log(arr); // blackpink 传字符串就输出字符串传数字就输出数字
}
fn.apply(a, ['blackpink'])
// fn.apply() // this->window arr->undefined
典型应用包括借助数学内置对象进行数组求值。
var arr = [1, 66, 3, 99, 4]
// var max = Math.max.apply(null, arr) // 虽然这里的this指向不需要改变填null没有错
var max = Math.max.apply(Math, arr) // 但是这里最好是让this指向函数的调用者是最合适的
var min = Math.min.apply(Math, arr)
console.log(max); // 99
console.log(min); // 1
bind()函数详解
基本介绍
bind意为绑定。bind()方法不会立即调用原函数,但能够改变函数内部的this指向。
语法结构
fn.bind(thusArg, arg1, arg2, ...)
参数说明:thisArg为函数运行时指定的this值;arg1, arg2等为后续传递的参数。
主要特点
- 不会立即调用原函数,即不执行原函数逻辑;
- 可以改变原函数内部的this指向;
- 返回一个由指定this值和初始化参数改造后的新函数。
返回值说明
- 返回由指定的this值和初始化参数改造的原函数拷贝。
主要应用场景
var c = {
name: '大华'
}
function fn() {
console.log(this); // {name: '大华'}
console.log(a + b); // 3
}
// fn.bind(c) // 这里不会有输出值
var f = fn.bind(c, 1, 2)
f() // 拷贝函数所以输出值用函数调用
典型应用:当函数不需要立即调用但希望改变其内部this指向时,使用bind()。例如:点击发送验证码后,60秒内禁止二次点击的场景。
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
var btns = document.querySelectorAll('button')
for (var i = 0; i < btns.length; i++) {
btns[i].onclick = function() {
this.disabled = true // 这个this指向的是调用者btn
setTimeout(function() {
// this.disabled = false; // 只用这一个不加bind的话会不管用,因为定时器里面的this指向的是window
this.disabled = false // 此时这里的this指向的是当前点击的那个btn
}.bind(this), 3000) // 这个this指向的是btn这个对象
}
}
三者区别总结
相同点
- 三者均可改变函数内部的this指向。
不同点
call和apply会立即调用函数,并改变函数内部this指向;call和apply的传参方式不同,call接受参数列表形式(arg1, arg2...),而apply必须接受数组形式 [arg];bind不会直接调用函数,但能改变函数内部this指向;
应用场景不同:
call常用于实现继承;apply常与数组相关,例如借助数学对象求数组最大最小值;bind用于不立即调用函数但需改变this指向的场景,如改变定时器内部this指向;
以上即为JavaScript中call、apply和bind函数的区别与使用方法,更多关于这3个函数的使用方法请查看下面的相关链接