// 1.实现一个apply函数
// 思路就是 将要改变this指向的方法挂到目标this上执行并返回
Function.prototype.myapply = function (context) {
if(typeof this !== 'function') {
throw new TypeError('not function')
}
context = context || window
context.fn = this
let result
if(arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result;
}
写法2
Function.prototype.apply2 = function(context, arr) {
context = context ? Object(context) : window;
var fn = fnFactory(context);
context[fn] = this;
var result;
if(!arr) {
result = context[fn]();
} else {
var args = [];
for(var i = 0, len = arr.length; i < len; i ++) {
args.push("arr["+ i +"]")
}
result = eval("context[fn]("+ args +")")
}
delete context[fn];
return result;
}
Function.prototype.apply2 = function(context, arr) {
// 1. 若是传入的context是null或者undefined时指向window;
// 2. 若是传入的是原始数据类型, 原生的call会调用 Object() 转换
context = context ? Object(context) : window;
// 3. 创建一个独一无二的fn函数的命名
var fn = fnFactory(context);
// 4. 这里的this就是指调用call的那个函数
// 5. 将调用的这个函数赋值到context中, 这样之后执行context.fn的时候, fn里的this就是指向context了
context[fn] = this;
var result;
// 6. 判断有没有第二个参数
if (!arr) {
result = context[fn]();
} else {
// 7. 有的话则用args放每一项的字符串: ['arr[0]', 'arr[1]']
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push("arr[" + i + "]");
}
// 8. 使用eval()来执行fn并将args一个个传递进去
result = eval("context[fn](" + args + ")");
}
// 9. 给context额外附件了一个属性fn, 所以用完之后需要删除
delete context[fn];
// 10. 函数fn可能会有返回值, 需要将其返回
return result;
};
es6实现:
Function.prototype.apply3 = function(context,arr) {
context = context ? Object(context) : window;
let fn = Symbol();
context[fn] = this;
let result = arr ? context[fn](...arr) : context[fn]();
delete context[fn];
return result;
}
扫码加群
