bind
bind的主要作用是将函数绑定到某个对象上,他返回的是一个函数
bind的模拟实现
Function.prototype.bind2 = function (context) {
//获得调用的bind的函数,用this获取
var self = this;
// 获取后面的一系列参数
var args = Array.prototype.slice.call(arguments, 1);
// 创建一个空函数作为中转,以免原型链污染
var fNOP = function () {};
var fBound = function () {
// 这里的arguments是指bind返回的函数中传入的参数
var bindArgs = Array.prototype.slice.call(arguments);
// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值
// 以上面的是 demo 为例,如果改成 `this instanceof fBound ? null : context`,实例只是一个空对象,将 null 改成 this ,实例会具有 habit 属性
// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
// 中转的空函数的原型链作为this的原型链,避免污染
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
call
call是Function原型上的方法,他是用来改变绑定的this值并且执行函数的,可以这样使用它。
f.call(o)
这个意思就是在对象o的环境下来调用f函数,也就是把this挂在在了o上。
call的第一个函数固定表示需要绑定的this值,后续的参数为函数调用时的参数
f.call(o,a,b,c)
等同于在o的环境下调用f(a,b,c)
call的模拟实现
Function.prototype.call2 = function (context) {
// 首先要获取调用call的函数,用this可以获取
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
}
var result = eval('context.fn(' + args +')');
delete context.fn
return result;
}
apply
apply方法和call大致相同,不同的地方在于他的第二个函数是个数组
调用方式为
f.apply(o,[a,b,c])