function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'}
Hello, Rebecca!!!
function () {return this.greeting + ', ' + this.name + '!!!';}, {greeting: 'Hello', name: 'Rebecca'}Hello, Rebecca!!!
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,[])
function speak(fn, obj) { return fn.apply(obj, obj); }