冴羽大佬分析bind连接:https://github.com/mqyqingfeng/Blog/issues/12
下面是菜鸡的逐句分析:
Function.prototype.bind = function(context) {
// 判断是否是函数调用bind, 如果不是bind则抛出异常
if(this instanceof !== 'function') {
throw new Error('亲,只有函数才可以调用bind哦!')
}
// 因为arguments是一个伪数组,所以这样取值arguments,不包括第一个参数
let arg = Array.prototype.slice.call(arguments, 1) // 这个等价于 [...arguments].slice(1)
// 将this保存,如果函数里面直接用this,会指向window
let that = this
//call 返回的是一个方法所以
let fBound = function() {
// 因为bind返回的是个函数,函数还可以第二次传参,secoundArg是第二次传入的参数
let secoundArg = Array.prototype.slice.call(arguments)
/*
这里return为什么要判断呢?只用context, arg.concat(secoundArg)不行吗?
不行,因为bind函数应用之后生成的函数可以直接使用,也可以new出来,那和bind有什么关系呢,bind的指针发了变化,如果是作为 普通函数的使用的话this指针指向bar,构造函数的话会指向obj实例
*/
return that.apply(this instanceof fBound ? this : context, arg.concat(secoundArg))
}
// 修改返回函数的 prototype 为绑定函数的 prototype,实例就可以继承绑定函数的原型中的值
fBound.prototype = this.prototype
return fBound
}
var value = 2;
var foo = {
value: 1
};
下面是call的输出:
var foo = {
value : 1
}
function bar(name, age) {
this.habit = 'shopping';
console.log(this.value); // undefined 因为this指向了obj,因为new会让指针指向实例
console.log(name); // daisy
console.log(age); // 18
}
bar.prototype.friend = 'kevin';
var bindFoo = bar.bind(foo, 'daisy');
var obj = new bindFoo('18');
// var obj = new bindFoo();
console.log(obj.habit); // shopping
console.log(obj.friend); // kevin