Open LLwanran opened 4 years ago
所有准备面试的同学,乍一看这个题目,嘿嘿一笑,so easy!我觉得十个同学,有九个都能回答上来。
如果这道题满分是 10 分,我们尝试来回答一下,看看能拿几分?
这三个函数都是改变了当前函数的 this 指向。
此时我的内心 OS:“妥妥的!心里美滋滋,正好是我准备的题目,下一题把”!
but,此时面试官再次发问:“你能讲讲它们三个的实现原理吗?能自己实现一下这三个函数吗?”
我:.....
我们重点讲一下 call 的用法和源码实现,其余的 apply 和 bind 道理一样。
call 的基本用法
function add(c, d) {
console.log(this.a + this.b + c + d);
}
var o = {a: 1, b: 2};
add.call(o, 3, 4);
如果我们不用 call,怎么实现这样的效果?
function add(c, d) {
console.log(this.a + this.b + c + d);
}
var o = {a: 1, b: 2};
// add.call(o, 3, 4);
o.add = add;
o.add(3, 4);
delete o.add;
我们能看到就三步:
其实就是利用了,object 的属性的 this 指向该 object 的特性来实现的哦。
我们尝试用源码实现一下
Function.prototype.call(context, ...args)
{
context = context || window; // context 如果是 null,则指向 window
context.fn = this;
var result = context.fn(...args);
delete context.fn;
return result;
}
apply 和 call 是一个道理
Function.prototype.apply(context, args)
{
context = context || window;
context.fn = this;
var result = context.fn(...args);
delete context.fn;
return result;
}
bind 有一点特殊,但是道理都是一个道理。
我们先写个例子看看 bind 怎么用
function add(c, d) {
console.log(this.a + this.b + c + d);
}
var o = {a: 1, b: 2};
var bindAdd = add.bind(o, 3);
bindAdd(4);
来看看源码怎么实现
Function.prototype.bind = function (context, ...rest) {
var self = this;
return function F(...args) {
return self.apply(context, rest.concat(args)); // 两次的参数 rest,args 合并到一起,作为函数的参数
}
}
此时我的内心 OS:“哈哈哈哈哈,我好机智,准备的太全了!”!
面试官内心 OS:“还行吧,不过不要高兴的太早了。”
面试官问:你能告诉下面程序的输出是什么吗?
function add(c, d) {
console.log(this.a + this.b + c + d);
}
var o = {a: 1, b: 2};
var bindAdd = add.bind(o, 3);
new bindAdd(4);
我们可以看到上面的程序仅仅是增加了一个new
,但是它的输出变成了NaN
,为什么?这是因为:" bind 返回的函数作为构造函数的时候,bind 时指定的 this 值会失效,但传入的参数依然生效"
我们再来丰富下bind
的实现
Function.prototype.bind = function (context, ...rest) {
var self = this;
return function F(...args) {
/*如果是 new 的,则不要之前的 context 啦*/
if (this instanceof F) {
return self(...rest, ...args);
}
return self.apply(context, rest.concat(args));
}
}
到这里应该已经结束了,但你以为你能拿满分了?too native!
面试官继续提问了:"你能讲讲 new 的原理吗?"
我:"….."
其实这道题最想教的不是这道题怎么来回答,而是想说明几点:
打个广告:去年写的一个面试题汇总《前端小白半年准备,成功进入BAT》
面试公司: 51信用卡
面试环节: 一面
问题: 请说明 apply,call,bind 的区别及用法