call bind apply的区别以及源码的手写
2025年8月6日
5分钟阅读
2 次浏览
0 条评论
call方法的第一个参数也是this的指向,后面传入的是一个参数列表改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次 当第一个参数为null、undefined的时候,默认指向window(在浏览器中) `js function fn(...args) { console.log(this的指向为${this}, args) } let obj = { ...
call
call
方法的第一个参数也是this
的指向,后面传入的是一个参数列表改变this
指向后原函数会立即执行,且此方法只是临时改变this
指向一次
当第一个参数为null
、undefined
的时候,默认指向window
(在浏览器中)
js1function fn(...args) {
2 console.log(`this的指向为${this}`, args)
3}
4let obj = {
5 myName: '张三',
6}
7
8fn.call(obj, 1, 2) // this会变成传入的obj,传入的参数是一个参数列表;
9fn(1, 2) // this指向window
10fn.call(null, [1, 2]) // this指向window
11fn.call(undefined, [1, 2]) // this指向window
apply
apply
接受两个参数,第一个参数是this
的指向,第二个参数是函数接受的参数,以数组的形式传入
改变this
指向后原函数会立即执行,且此方法只是临时改变this
指向一次
当第一个参数为null
、undefined
的时候,默认指向window
(在浏览器中)
js1function fn(...args) {
2 console.log(`this的指向为${this}`, args)
3}
4let obj = {
5 myName: '张三',
6}
7
8fn.apply(obj, [1, 2]) // this会变成传入的obj,传入的参数必须是一个数组;
9fn(1, 2) // this指向window
10fn.apply(null, [1, 2]) // this指向window
11fn.apply(undefined, [1, 2]) // this指向window
bind
bind 方法和 call 很相似,第一参数也是this
的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
改变this
指向后不会立即执行,而是返回一个永久改变this
指向的函数
JS1function fn(...args){
2 console.log(`this的指向为${this}`,args);
3}
4let obj = {
5 myName:"张三"
6}
7
8const bindFn = fn.bind(obj,[1,2]); // this 会变成传入的obj ,bind不是立即执行
9bindFn(1,2) // this指向obj
10fn(1,2) // this指向window
手写 apply
- 判断是否为 undefined 或 null,如果是,则 this 指向的是 window
- 给目标对象创建一个属性,将要调用的方法绑定到这个属性上
- 用 arguments 拿到传入的参数
- 直接运行刚刚创建的属性
- 删除这个属性
js1Function.prototype.myApply = function(context) {
2 if (typeof context === 'undefined' || context === null) {
3 context = window
4 }
5
6 context.fn = this //this指向的是apply方法的函数
7 let args = arguments[1] //拿到第一个参数
8 let result
9 if (args) {
10 result = context.fn(...args) //运行一下
11 } else {
12 result = context.fn()
13 }
14 delete context.fn
15 return result
16}
手写 call
思路同 apply 基本相同
不一样的是要通过 arguments 取出除第一位之外的所有参数放到一个数组里,然后通过展开运算符给要执行的函数或方法传参
js1//往Function的原型对象上加myCall方法
2Function.prototype.myCall = function(context) {
3 //判断是否为undefined或null
4 if (typeof context === 'undefined' || context === null) {
5 context = window
6 }
7 context.fn = this //给目标对象新建一个属性,绑定这个函数
8 let args = [...arguments].slice(1) //过arguments取出除第一位之外的所有参数放到一个数组
9 let result = context.fn(...args) ////运行一下
10 delete context.fn //删除目标对象上的fn属性
11 return result
12}
手写 bind
bind() 方法会创建一个新函数。 当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this, 之后的一序列参数将会在传递的实参前传入作为它的参数
要注意因为 bind 转换后的函数可以作为构造函数使用,此时 this 应该指向构造出的实例
js1Function.prototype.myBind = function(context) {
2 if (typeof this !== 'function') {
3 throw new TypeError('error')
4 }
5 // 获取参数
6 const args = [...arguments].slice(1)
7 let _this = this
8 return function fn() {
9 //判断是都被当做构造函数使用,根据调用方式,传入不同绑定值
10 return _this.apply(
11 this instanceof fn ? new fn(...arguments) : context,
12 args.concat(...arguments)
13 )
14 }
15}
小结
- 三者都可以改变函数的 this 指向
- 三者的第一个参数都是 this 要指向的对象,如果没有这个参数,或者参数为 undefined 或 null,则默认会指向全局 window
- 三者都可以传参,apply 接受的是数组,call 和 bind 接收的是参数列表,bind 的参数列表可以分为多次传入
- apply 和 call 是立即执行,而 bind 是返回绑定后的那个 this 之后的函数
喜欢这篇文章吗?
加载中...
评论
0 条登录后即可参与评论讨论
加载评论中...
相关文章
目录