奔着一星期彻底弄清楚一个javascript小知识点的目的,这次的目标是call apply bind方法
在实际项目中,经常会用到这三个函数,只是简单的知道,都是用来进行上下文绑定的,这三个函数都可以实现,现在看来这三者还是有很大区别的,特别是bind和其他两个的区别
先说call和apply 目的是改变函数的执行上下文,下面列举一些他们的用法
实例一
const zhangsan = {
name: '张三',
age: 18
}
const lisi = {
name: '李四',
age: 16
}
function introduce(grade) {
console.log(`我的名字叫${this.name},我今年${this.age}岁了,上${grade}了`)
}
introduce.call(zhangsan, 3) // 我的名字叫张三,我今年18岁了,上3了
introduce.call(lisi, 4) // 我的名字叫李四,我今年18岁了,上3了
introduce.apply(zhangsan, [3])// 我的名字叫张三,我今年18岁了,上3了
introduce.apply(lisi, [4]) // 我的名字叫李四,我今年18岁了,上3了
实例二
const People = {
name: '党',
age: 100,
introduce: function(grade) {
console.log(`我的名字叫${this.name},我今年${this.age}岁了,上${grade}了`)
}
}
People.introduce('大学') // 我的名字叫党,我今年100岁了,上大学了
const zhangsan = {
name: '张三',
age: 18
}
People.introduce.call(zhangsan, 3) // 我的名字叫张三,我今年18岁了,上3了
People.introduce.apply(zhangsan, [3]) // 我的名字叫张三,我今年18岁了,上3了
通过以上两个例子,可以看出,call和apply的区别主要在于传递参数的上的不同,
他们俩的第一个参数都是要执行环境的this, 也就是说执行函数的上下文
第二个参数apply是以数组的方式以此传递, call要一个一个传
需要注意的一点,他们的第二个参数都可以穿arguments
下面就看下bind函数的具体用法
还是老样子,列举一些例子,例子更能直观的感受其用法
还是以上面代码为基础
const wangwu = {
name: '王五',
age: 20
}
People.introduce.bind(wangwu, 4) // ƒ (grade) {
// console.log(`我的名字叫${this.name},我今年
// ${this.age}岁了,上
// }
可以看到输出的是一个函数体
所以, bind后函数不会执行, 只是返回一个改变上下文的函数副本, 而call和apply是直接执行的函数
如果想得到和call apply一样的效果,需要手动执行下改函数
People.introduce.bind(wangwu, 4)() // 我的名字叫王五,我今年20岁了,上4了
查了下bind在ie6 ~ ie8下bind的兼容性不好,如果需要兼容ie低版本浏览器的,需要模拟其用法
代码如下
if(!function(){}.bind) {
Function.prototype.bind = function(context) {
const self = this
const args = Array.prototype.slice.call(arguments)
return function() {
return self.apply(context, args.slice(1))
}
}
}
细想下来,上面这段代码的知识点特别多
- const self = this
通过上面两个截图可以很明确的知道需要让this保存调用它的值
- 需要扩展方法的时候,都需要先判断是否已经存在,如果不存在则会在原型prototype上添加方法
- 将伪数组转化为真正的数组 Array.protoype.slice.call(arguments)
数组slice的用法,具体怎么使用可以参考这个 - 返回一个函数,把该函数传递给bind的第一个参数当做执行上下文, 由于args已经是一个数组,排除第一项,之后的参数作为第二部分参数传给apply。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。