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)(); }