资讯专栏INFORMATION COLUMN

聊一聊call、apply、bind的区别

kohoh_ / 2050人阅读

摘要:指定的参数列表语法在函数运行时指定的值。需要注意的是,指定的值并不一定是该函数执行时真正的值,如果这个函数处于非严格模式下,则指定为或时会自动指向全局对象浏览器中就是对象,同时值为原始值数字,字符串,布尔值的会指向该原始值的自动包装对象。

我们都知道call apply bind都可以改变函数调用的this指向。那么它们三者有什么区别,什么时候该用哪个呢?
我们先直接通过代码实例来了解,后面再借助专业文档来解释。

举个?
// 有只猫叫小黑,小黑会吃鱼
const cat = {
    name: "小黑",
    eatFish(...args) {
        console.log("this指向=>", this);
        console.log("...args", args);
        console.log(this.name + "吃鱼");
    },
}
// 有只狗叫大毛,大毛会吃骨头
const dog = {
    name: "大毛",
    eatBone(...args) {
        console.log("this指向=>", this);
        console.log("...args", args);
        console.log(this.name + "吃骨头");
    },
}

console.log("=================== call =========================");
// 有一天大毛想吃鱼了,可是它不知道怎么吃。怎么办?小黑说我吃的时候喂你吃
cat.eatFish.call(dog, "汪汪汪", "call")
// 大毛为了表示感谢,决定下次吃骨头的时候也喂小黑吃
dog.eatBone.call(cat, "喵喵喵", "call")

console.log("=================== apply =========================");
cat.eatFish.apply(dog, ["汪汪汪", "apply"])
dog.eatBone.apply(cat, ["喵喵喵", "apply"])

console.log("=================== bind =========================");
// 有一天他们觉得每次吃的时候再喂太麻烦了。干脆直接教对方怎么吃
const test1 = cat.eatFish.bind(dog, "汪汪汪", "bind")
const test2 = dog.eatBone.bind(cat, "喵喵喵", "bind")
test1()
test2()

好了例子很简单但是基本的使用方法跟场景都涉及到了。

callapply的用法几乎一样,唯一的不同就是传递的参数不同,call只能一个参数一个参数的传入。
apply则只支持传入一个数组,哪怕是一个参数也要是数组形式。最终调用函数时候这个数组会拆成一个个参数分别传入。
至于bind方法,他是直接改变这个函数的this指向并且返回一个新的函数,之后再次调用这个函数的时候this都是指向bind绑定的第一个参数。bind传餐方式跟call方法一致。

由于apply函数传参的特殊性,我们又衍生出了一个黑魔法。
// 如果一个数组我们已知里面全都是数字,想要知道最大的那个数,由于Array没有max方法,Math对象上有
// 我们可以根据apply传递参数的特性将这个数组当成参数传入
// 最终Math.max函数调用的时候会将apply的数组里面的参数一个一个传入,恰好符合Math.max的参数传递方式
// 这样变相的实现了数组的max方法。min方法也同理
const arr = [1,2,3,4,5,6]
const max = Math.max.apply(null, arr)
console.log(max)    // 6
这里bind函数也有一个小技巧
// 如果你想将某个函数绑定新的`this`指向并且固定先传入几个变量可以在绑定的时候就传入,之后调用新函数传入的参数都会排在之后
const obj = {}
function test(...args) {console.log(args)}
const newFn = test.bind(obj, "静态参数1", "静态参数2")
newFn("动态参数3", "动态参数4")

接着来看看MDN文档 call语法

fun.call(thisArg, arg1, arg2, ...)

thisArg: 在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。

arg1, arg2, ... 指定的参数列表

apply语法

fun.apply(thisArg, [argsArray])

thisArg 在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。

argsArray 一个数组或者类数组对象,其中的数组元素将作为多带带的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。

bind语法

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

thisArg 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。

arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

总结

当我们使用一个函数需要改变this指向的时候才会用到call`apply`bind

如果你要传递的参数不多,则可以使用fn.call(thisObj, arg1, arg2 ...)

如果你要传递的参数很多,则可以用数组将参数整理好调用fn.apply(thisObj, [arg1, arg2 ...])

如果你想生成一个新的函数长期绑定某个函数给某个对象使用,则可以使用const newFn = fn.bind(thisObj); newFn(arg1, arg2...)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90774.html

相关文章

  • underscore 源码解读之 bind 方法实现

    摘要:概括地讲,如果构造函数有返回值,且返回值是对象不能是,那么对其进行操作返回该对象,否则返回构造实例。所以在方法中,我们需要进一步判断这个构造函数有没有返回值,返回值是不是对象。 自从进入七月以来,我的 underscore 源码解读系列 更新缓慢,再这样下去,今年更完的目标似乎要落空,赶紧写一篇压压惊。 前文 跟大家简单介绍了下 ES5 中的 bind 方法以及使用场景(没读过的同学建...

    xiaodao 评论0 收藏0
  • 面试知识点总结

    摘要:最近面试几家前端职位,想知道目前的前端面试题是偏向哪一块,都主要问到的是语法,闭包,原型链,继承那一块。并且将面试题的知识点汇总一下。参考网站面试题图片过多的时候如何优化图标很多的时候可以用雪碧图图片过大时候可以压缩一下。 最近面试几家前端职位,想知道目前的前端面试题是偏向哪一块,都主要问到的是ES6语法,闭包,原型链,继承那一块。并且将面试题的知识点汇总一下。有助于下次面试。 1.H...

    王晗 评论0 收藏0
  • 面试知识点总结

    摘要:最近面试几家前端职位,想知道目前的前端面试题是偏向哪一块,都主要问到的是语法,闭包,原型链,继承那一块。并且将面试题的知识点汇总一下。参考网站面试题图片过多的时候如何优化图标很多的时候可以用雪碧图图片过大时候可以压缩一下。 最近面试几家前端职位,想知道目前的前端面试题是偏向哪一块,都主要问到的是ES6语法,闭包,原型链,继承那一块。并且将面试题的知识点汇总一下。有助于下次面试。 1.H...

    CrazyCodes 评论0 收藏0
  • 听飞狐聊JavaScript设计模式系列03

    摘要:闭包与柯里化闭包有权访问另一个函数作用域中变量的函数。柯里化把接受多个参数的函数变换成接受一个单一参数最初函数的第一个参数的函数,并且返回接受余下的参数而且返回结果的新函数的技术。 本回内容介绍 上一回聊到JS的Object类型,简单模拟了一下Java的Map,介一讲,偶们来聊一下函数好唔好,介可系JS世界的一等公民哟。从函数开始,我们就将逐步过渡到设计模式,来吧,帅狐带你装逼带你飞:...

    levy9527 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<