function wrapExplicit(fn) {
return function(a1, a2, a3) {
return fn.call(this, this, a1, a2, a3)
}
}
function wrapApply(fn) {
return function() {
var args = [this]
for (let i = 0, len = arguments.length; i < len; i++) {
args[i + 1] = arguments[i]
}
return fn.apply(this, args)
}
}
function wrapApplyWithArguments(fn) {
return function() {
return fn.apply(this, [this].concat(arguments))
}
}
function fn(thisArg, a1, a2, a3) {
thisArg.result = a1 + a2 + a3
}
var explicitCall = { fn: wrapExplicit(fn) }
var applyCall = { fn: wrapApply(fn) }
var applyWithArgumentsCall = { fn: wrapApplyWithArguments(fn) }