JS面试中你不知道的call apply bind方法及使用场景详解
目录
- 面试
- 三者区别
- call
- apply.
- bind
- 总结
- 应用场景
- 简单实现
- call
- apply
- bind
面试
面试官 :说一下 call apply bind 的三者区别吧?
我:啊.....这。
三者区别
call
我们先来看看 call
call 函数接收两个参数
@params1
需要指向this
@params2
需要携带的参数
就拿这段代码 来说 我调用 foo 函数 的时候 想去 执行obj 中的 eat函数 怎么办?
默认 我的 foo 里面什么页面有 怎么可能会打印 吃饭呢?this默认指向 window ,window 对象中 没有 eat 方法不应该 报错 not defind 吗?
let obj = { eat: function (args) { console.log("吃饭", args); } } function foo(...args) { this.eat(args) }
你可以这样 , 此时调用的时候 foo 的函数 this 就指向了 obj 但是只是这一次调用哦 ,下次 this 是指向 window
的
console.log(foo.call(obj, 123, 456)); / / 吃饭 [ 123, 456 ]
调用结果
: 传入 this 和 参数 立即执行函数
apply.
@params1
需要指向this
@params2
需要携带的参数 传入的参数数据类型为 Array
let obj = { eat: function (args) { console.log("吃饭", args); } } function foo(...args) { this.eat(args) }
console.log(foo.apply(obj, [1, 2, 3])); // 吃饭 [1,2,3 ]
调用结果
: 传入 this 和 参数,立即执行
bind
@params1
需要指向this
@params2
需要携带的参数
let obj = { eat: function (args) { console.log("吃饭", args); } } function foo(...args) { this.eat(args) }
console.log(foo.bind(obj, 1, 2, 3)()); //吃饭 [ 1, 2, 3 ]
调用结果 : 传入 this 和 参数 返回一个 新的函数,不会立即执行
总结
call
函数 传入绑定 this的对象 ,携第二个参数以 参数列表形式传入 并会立即执行
apply
函数 传入绑定 this的对象 第二个参数以 数组的形式 传入 并会立即执行
bind
函数 传入绑定 this的对象 第二个参数以 数组或参数列表的形式传入 不会立即执行函数会返回一个新的函数 自由调用
应用场景
利用call 实现 构造函数原型继承
function Person(name, age, friends) { this.friends = friends this.name = name this.age = age } Person.prototype.eat = function () { console.log(`${this.name}在吃饭`); } Person.prototype.running = function () { console.log(`${this.name}去跑步了`); } function Student(study, name, age, friedns) { Person.call(this, name, age, friedns) this.study = study } function Teacher(plaseLoveStudent) { this.plaseLoveStudent = plaseLoveStudent } //继承 person Student.prototype = new Person() const stu = new Student('语文', "张三", 18, ['王安石']) const stu2 = new Student('数学', "李四", 18, ['哈利波特']) const tec = new Teacher("王安怡") console.log(stu === stu2); console.log(stu); console.log(stu.friends); console.log(stu2.friends);
简单实现
call
实现思路 :
1:在Function 原型身上添加一个方法。
2:mycall 接受 两个参数 一个是绑定的 this,还有就是 参数列表
3:保存调用者,其实这里更严谨一点还需要判断调用者的 类型
4:判断传入的thisArgs 是不是 undefined 或者 null 如果是 则 this指向 window 否则将 绑定的 this封装成 一个对象
5:然后将 函数本身保存在 上面封装好的对象中
6:调用并传入args
7:完成实现 this指向的改变
Function.prototype.mycall = function (thisArgs, ...args) { /** * * 保存this(当前调用者) * */ const newFunc = this // 在当前调用者 this身上 保存 调用者 thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window thisArgs.func = newFunc thisArgs.func(...args) }
apply
apply 就不说了 实现思路是一样的 只不过传入的参数不一样做一个判断就行了
Function.prototype.myapply = function (thisArgs, argArray) { if (!(argArray instanceof Array)) { throw '参数类型限定为 Array' } else { const func = this thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window thisArgs.fn = func thisArgs.fn(argArray) } }
bind
bind 跟 apply call 有一些区别
bind 会返回一个新的函数 , 所以我们在内部需要自己定义一个 函数 给返回出去, 并且,可能出现 返回新函数调用时 继续传入参数 所以我们需要将参数合并
Function.prototype.mybind = function (thisArgs, ...argArray) { const oldFunc = this console.log(this); thisArgs = (thisArgs !== undefined && thisArgs !== null) ? Object(thisArgs) : window function proxyFn(...args) { thisArgs.func = oldFunc const funcCallResult = thisArgs.func([...argArray, ...args]) // 合并两次的 参数 delete thisArgs.func return funcCallResult } return proxyFn }
谢谢,到此就完成了简单版的 call apply bind 的实现,更多关于JS call apply bind方法的资料请关注我们其它相关文章!