call
call方法的特点:
一个函数通过.call()
就相当于这个函数执行。
这个函数中 this 的指向就是call方法中的第一个参数。
call方法中从第二个参数开始之后,都是调用call方法函数的参数。
Function.prototype.myCall = function (ctx) {
ctx = ctx ? Object(ctx) : window;
ctx.originFn = this;
var args = [];
for (var i = 1; i < arguments.length; i ++) {
args.push('arguments[' + i + ']');
}
console.log(args);
var res = eval('ctx.origin(' + args + ')');
delete ctx.originFn;
return res;
}
apply
apply方法的特点:
一个函数通过.apply()
就相当于这个函数执行。
这个函数中 this 的指向就是call方法中的第一个参数。
apply方法的第二个参数是一个数组,里面是调用apply方法函数的参数。
apply方法只取到第二个参数,后面的忽略。
如果第二个参数是undefined、null、object、function,不报错但是arguments的length为0。
如果第二个参数是原始值,直接报错。
Function.prototype.myApply = function (ctx, args) {
ctx = ctx ? Object(ctx) : window;
ctx.originFn = this;
if (args === undefined || args === null) {
return ctx.originFn();
}
if (typeof args !== 'object' && typeof args !== 'function') {
throw new Error('createListFormArrayLike called on non-object');
}
if (({}).toString.call(args) !== '[object Array]') {
return ctx.originFn();
}
var res = eval('ctx.originFn(' + args + ')');
delete ctx.originFn;
return res;
}
bind
bind方法的特点:
一个函数通过.bind()
之后不会立即执行,而是返回一个新的函数。
这个函数中 this 的指向就是bind方法中的第一个参数。
bind方法从第二个参数开始,后面是调用bind方法函数的参数。
bind方法可以接收一部分参数,返回的新函数可以接收另一部分参数。
返回的新函数通过new执行(实例化),this指向原本的函数构造出来的实例。
实例继承原函数构造函数上的原型。
Function.prototype.myBind = function (ctx) {
var originFn = this,
args = [].slice.call(arguments, 1),
_tempFn = function () {};
var newFn = function () {
var newArgs = [].slice.call(arguments),
context = this instanceof newFn ? this : ctx;
return originFn.apply(context, args.concat(newArgs));
}
_tempFn.prototype = originFn.prototype;
newFn.prototype = new _tempFn();
return newFn;
}