function speak(fn, obj) { if(fn.bind){ return fn.bind(obj)();} else{ return fn.apply(obj,[]); } }
分析题意:书写一个函数speak,该函数接收两个参数,一个是个函数fn,一个是个对象obj.希望将传入的函数的上下文绑定成传入的对象obj.
使得fn调用后,内部变量的值都取得obj的属性值.
因此,这是一道函数作为参数传入的高阶函数应用与call,apply方法知识点联合考查的题目
//解法一:利用call方法:
function speak(fn, obj) {
return fn.call(obj);
}
//解法二:利用apply方法:
function speak(fn, obj) {
return fn.call(obj);
}
function speak(fn, obj) { if (!Function.prototype.call) { Function.prototype.call = function (ctx) { let args = []; ctx.fn = this; for (var i = 1; i < arguments.length; i++) { args.push("arguments[" + i + "]"); } var result = eval("ctx.fn(" + args + ")"); delete ctx.fn; return result; }; } if (!Function.prototype.apply) { Function.prototype.apply = function (ctx, args) { var temp = []; ctx.fn = this; for (var i = 0; i < args.length; i++) { temp.push("args[" + i + "]"); } var result = eval("ctx.fn(" + temp + ")"); delete ctx.fn; return result; }; } if (!Function.prototype.bind) { Function.prototype.bind = function (ctx) { var fnToBind = this; var slice = Array.prototype.slice; var args = slice.apply(arguments, 1); var fBound = function () { var restArgs = slice.apply(arguments); return fnToBind.apply( this instanceof fBound ? this : ctx, args.concat(restArgs) ); }; fBound.prototype = Object.create(fnToBind.prototype); fBound.constructor = fBound; return fBound; }; } return fn.call(obj); }复习一下手写。
function speak(fn, obj) { // 方法1 将函数fn直接挂载到obj上 obj.fn = fn; return obj.fn(); // // 方法2 使用apply // return fn.apply(obj); // // 方法3 使用call // return fn.apply(obj); // // 方法4 使用bind // return fn.bind(obj)(); }
fn.bind(obj)() fn.call(obj) fn.apply(obj,[])