bind方法跟call、apply的区别
在手动封装bind之前,首先来了解下js中改变this指向的三个方法区别及bind方法的特性。
call和aplly的第一个参数都是要改变上下文的对象,而call从第二个参数开始以参数列表的形式展现。
fn.call(obj, arg1, arg2, arg3…)
apply则是把除了改变上下文对象的参数放在一个数组里面作为它的第二个参数。如果call和apply第一个参数是null或者undefined,那么this的指向就是全局变量,在浏览器里就是window对象。
fn.apply(obj, [arg1, arg2, arg3…])
而bind方法不同于call、apply,call、apply,bind方法会创建一个新的函数,当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的参数将会在传递的实参前传入作为它的参数,这些参数是可以分开传递的,跟柯里化函数一样,等待参数传完,再来执行函数。
自己封装bind方法
代码实现
Function.prototype.newbind = function(fn) {
//判断调用newbind方法的是不是一个函数,不是报错
if (typeof this !== "function") {
throw new new Error('type error')
}
// 将this赋值给that
var that = this
// 因为arguments是个伪数组,所以这里用数组的方法来获取传参1项后面的参数,0项是改变this指向的参数不取
var agrs = [].slice.call(arguments, 1)
var f = function() {
// 获取后面继续没传完的参数的,跟前面的传好的参数,进行整合。
var _agrs = agrs.concat([].slice.call(arguments, 0))
//将当前指向newbind函数的this进行改变,第0项改变this指向的参数表示也需要更改的this指向,通过apply方法来改变
//this instanceof f判断的是当前是否被new过,如果new过了,则此时this应该指向构造函数本身(构造函数的this指向实例化对象);如果没有new过,则此时this应该指向传递过来的参数(实现改变this的指向)
return that.apply(this instanceof f ? this : (fn || window), _agrs)
}
//实现继承
f.prototype = {
constructor: f,
__proto__: this.prototype
}
return f
}
var x = 10;
var obj = {
x: 20
}
function show(a, b) {
console.log(this.x, a, b);
}
var newshow = show.newbind(obj, '嘻嘻')
newshow('哈哈')
输出的结果