@TOCjavascript
在咱们平常开发过程当中call、bind、apply无疑是咱们用的比较多的语法,今天在开发中看到有同事傻傻分不清call和bind的区别,故在解释一通以后,写下此文;java
从MDN 文档 call咱们能够了解到: call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。git
fun
函数运行时指定的 this
值*。*须要注意的是,指定的 this
值并不必定是该函数执行时真正的 this
值,若是这个函数在非严格模式
下运行,则指定为 null
和 undefined
的 this
值会自动指向全局对象(浏览器中就是 window 对象),同时值为原始值(数字,字符串,布尔值)的 this
会指向该原始值的自动包装对象。(ps:严格模式下 咱们对函数的的调用必须严格的写出被调用的函数的对象);先举个例子:github
// main.js
const foo={
name:'foo',
getFoo(...args){
console.log('this===',this,'this.name==',this.name)
console.log('-----------------------------------')
console.log('...args=====',...args)
}
}
const bar={
name:'bar',
getBar(...args){
console.log('this===',this,'this.name==',this.name)
console.log('-----------------------------------')
console.log('...args=====',...args)
}
}
foo.getFoo() //this=== {name: "foo", getFoo: ƒ} this.name== foo ----------------------------------- ...args=====
bar.getBar() //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args=====
复制代码
假如咱们想在getFoo去借bar里面的东西用用,该怎么办呢? 也许有同窗想到的是这样:数组
foo.getFoo(bar.name) // this=== {name: "foo", getFoo: ƒ} this.name== foo ----------------------------------- ...args===== bar
复制代码
毫无疑问,这是没问题的,但此时只是正常的传参,可否干脆点把this.name也改为bar呢;根据call的定义:浏览器
foo.getFoo.call(bar,'测试传参','测试call') //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试call
//使用call后,咱们能够看到foo.getFoo的this此时指向了bar对象,此时的name拿到的bar的对象的name;
复制代码
从MDN 文档 apply咱们能够了解到: apply()
方法调用一个具备给定this
值的函数,以及做为一个数组(或相似数组对象)提供的参数。app
func.apply(thisArg, [argsArray])ide
thisArg:可选的。在 func
函数运行时使用的 this
值。请注意,this
可能不是该方法看到的实际值:若是这个函数处于非严格模式下,则指定为 null
或 undefined
时会自动替换为指向全局对象,原始值会被包装。函数
argsArray:可选的。一个数组或者类数组对象,其中的数组元素将做为单独的参数传给 func
函数。若是该参数的值为 null
或 undefined
,则表示不须要传入任何参数。从ECMAScript 5 开始可使用类数组对象。 浏览器兼容性 请参阅本文底部内容。测试
继续使用刚才的foo和bar
foo.getFoo.apply(bar,['测试传参','测试apply']) //his=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试apply
复制代码
总结 call方法和apply方法二者极度类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
从MDN 文档 bind咱们能够了解到:
bind()方法建立一个新的函数,在调用时设置this关键字为提供的值。并在调用新函数时,将给定参数列表做为原函数的参数序列的前若干项。
function.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 调用绑定函数时做为this
参数传递给目标函数的值。 若是使用new
运算符构造绑定函数,则忽略该值。当使用bind
在setTimeout
中建立一个函数(做为回调提供)时,做为thisArg
传递的任何原始值都将转换为object
。若是bind
函数的参数列表为空,执行做用域的this
将被视为新函数的thisArg
。
arg1, arg2, ... 当目标函数被调用时,预先添加到绑定函数的参数列表中的参数。
emmmm...继续最最上面的那个foo和bar
foo.getFoo.bind(bar,'测试传参','测试bind') // 此时是无输出,由于bind()方法建立一个新的函数,当前函数并无执行
复制代码
修改以下:
const foobindbar = foo.getFoo.bind(bar,'测试传参','测试bind');
console.log(foobindbar)
// ƒ getFoo(...args){
// console.log('this===',this,'this.name==',this.name)
// console.log('-----------------------------------')
// console.log('...args=====',...args)
// }
foobindbar() //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试apply
复制代码
call方法和apply方法二者极度类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。用apply时,即便传入的参数只有一个,也必须定义为数组才行;
call与apply改变this的指向时,会直接触发函数;而bind会建立一个新的函数,在调用时设置this关键字为提供的值,使用bind时,会优先使用bind绑定的几个值; 以下:
foo.getFoo.bind(bar,'测试传参','测试bind')
const foobindbar = foo.getFoo.bind(bar,'测试传参','测试bind');
console.log(foobindbar)
// ƒ getFoo(...args){
// console.log('this===',this,'this.name==',this.name)
// console.log('-----------------------------------')
// console.log('...args=====',...args)
// }
foobindbar('参数1', '参数2') //this=== {name: "bar", getBar: ƒ} this.name== bar ----------------------------------- ...args===== 测试传参 测试apply 参数1 参数2
// ...args===== 测试传参 测试apply 参数1 参数2
复制代码
文章所示demo请转王一诺/github