JavaScript中的call、apply 和 bind

JavaScript中的call、apply 和 bind

1. Function.prototype.call()

函数实例的 call 方法,可以指定函数内部的 this 指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数

一句话概括 call 方法的作用:例如 a.call(obj) ,在 obj 的作用域中运行 a,

let obj = {};
let f = function() {
	return this;
}

f() === window   // true
f.call(obj) === obj // true

/*
	上面代码可以看出,全局环境下运行函数 f,this指向全局环境,call 方法可以改变 this 指向,指定 this 指向 obj,然后在对象 obj     的作用域下运行函数 f
*/

call 方法的参数,应该是一个对象。如果参数为空、nullundefined ,则默认传入全局对象

let n = 123;
var obj = { n: 456 };

let a = function() {
    console.log(this.n)
}

a.call() // 123
a.call(null) // 123
a.call(undefined) //123
a.call(window) // 123
a.call(obj) // 456

/*
	上面代码中 call 的方法的第一个参数如果是为空、null、undefined 等同于指向全局对象 window(浏览器为 window 对象),所以输出的都是 123
	call 方法的第一个参数如果是一个对象,则会子 obj 的作用域下调用函数 a ,所以输出 456
*/

如果函数第一个参数是一个原始值,那么这个原始值会自动转成对应的包装对象,然后传入 call 方法

function f() {
    consolelog(this)
}

f.call(5) // Number{5}
f.call('a') // String{'a'}

// call 中的第一个参数是一个原始值,会自动转化为包装对象,然后绑定到 this 中

call 方法还可以接受多个参数

第一个参数:所要指向的那个对象

后面的参数:函数调用时所需的参数

function add(a,b) {
    return a + b;
}
// 第一个参数 this 表示当前环境
add.call(this,1,2) // 3

/*
	call 方法指定函数 add 内部的 this 指定到当前环境,并且调用函数 add 时的参数为 1,2。所以返回 3
*/ 

2. Function.prototype.apply()

apply 方法与 call 方法的作用类似,也是改变 this 的指向,然后在调用该函数。唯一的区别就是,apply 接受一个数组作为函数执行的参数,使用格式如下

func.apply(obj,[arg1, arg2, ...])

apply 方法的第一个参数也是 this 所要指向的对象,如果设为 null 或 undefined ,则等同于只想全局对象。第二个参数则是一个数组,该数组中的所有元素依次传入原函数。

function f(x,y) {
    return x + y;
}

f.call(null, 1, 2) // 3
f.apply(null, [1, 2]) // 3

3. Function.prototype.bind()

bind() 方法用于将函数体内的 this 绑定到某个对象,然后返回一个新函数

function.bind(obj) 在 obj 的环境中运行 function 这个函数(记住这句话) ,相当于obj.function

let d = new Date()
d.getTime() // 1658922441747

let p = d.getTime
/*
	d.getTime 这个方法的执行上下文是 window
	换句话说就是:在 window 这个环境中运行 d.getTime,而 window 中没有 getTime 这个方法,所以报错
*/
p() // this is not a Date object.at getTime (<anonymous>)

上面代码中将 d.getTime 赋值给 p ,然后调用 p 会报错,这是因为 getTime() 方法内部的 this 绑定 Date 对象实例,赋值给 p 后,内部的 this 已经不在指向 Date 对象实例了

let p2 = d.getTime.bind(d)
/*
	上面那个代码的意思是将 d.getTime 这个方法的执行上下文变为 d,而 d 是一个 Date 实例
	换句话说就是在 Date 这个环境中运行 d.getTime 这个方法,而 Date 中有这个方法
*/
p2() // 1658922441747

bind() 方法将 getTime 内部的 this 绑定在 d 对象,这时就可以安全的将这个方法复制给其他变量了

bind() 方法的参数就是所要绑定的 this 对象

let counter = {
    count: 0,
    inc: function() {
        this.count++
    }
}

let func = counter.inc.bind(conuter)
func()
counter.count // 1

也可以将 this 绑定到其他对象

let counter = {
    count: 0,
    inc: function() {
        this.count++
    }
}

let obj = {
    count: 100
}

let func = counter.inc.bind(obj)  // 在 obj 的环境中运行 counter 里面的 inc 方法
func()
obj.count // 101

bind() 还可以接受更多的参数,将这些参数绑定到原函数的参数

let add = function(x,y) {
    return x * this.n + y * this.m
}

let obj = {
    n: 2,
    m: 2
}

let newAdd = add.bind(obj,5) // 将 5 传递给 add 函数的 x
newAdd(6) // 22   2*5+2*6

通过bind绑定的函数,原函数与新函数是不相等的

const fn1 = function () {
	console.log("Function1",this.a)
}

const obj = {
	a: 1
}

const fn2 = fn1.bind(obj)  // Function 1
fn1 // Function undefined
fn2 === fn1 // false
// 通过 bind 绑定的原函数与新函数不相等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Champion.XL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值