切换主题
函数方法
特别说明下,当通过下面三个方法(任意一个)调用箭头函数时,由于箭头函数自身没有
this
,故第一个参数会被忽略掉(即只能传参,不能绑定this
)。
更具体的例子可前往MDN
查看,传送门通过call
、apply
、bind
调用。
Function#call()
JavaScript
if (!Function.prototype.call) {
Function.prototype.call = function (ctx) {
if (typeof this !== 'function') {
throw new TypeError('call方法的调用标识符必须为函数!')
}
var ctx = ctx || window, args = [], ret
ctx.fn = this
for (var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']')
}
ret = eval('ctx.fn(' + args + ')')
delete ctx.fn
return ret
}
}
关于eval()函数:
eval()
函数可计算某个字符串,并执行其中的JavaScript
代码。
替代方案
JavaScript
if (!Function.prototype.call) {
Function.prototype.call = function (ctx) {
if (typeof this !== 'function') {
throw new TypeError('call方法的调用标识符必须为函数!')
}
var ctx = ctx || window, args = [], ret
ctx.fn = this
for (var i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i])
}
ret = new Function('ctx', 'args', 'return ctx.fn(...args)')(ctx, args)
delete ctx.fn
return ret
}
}
Function#apply()
JavaScript
if (!Function.prototype.apply) {
Function.prototype.apply = function (ctx, arr) {
if (typeof this !== 'function') {
throw new TypeError('apply方法的调用标识符必须为函数!')
}
var ctx = ctx || window, args = [], ret
ctx.fn = this
if (!arr) {
ret = ctx.fn()
} else {
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']')
}
ret = eval('ctx.fn(' + args + ')')
}
delete ctx.fn
return ret
}
}
Function#bind()
JavaScript
if (!Function.prototype.bind) {
Function.prototype.bind = function (ctx) {
if (typeof this !== 'function') {
throw new TypeError('bind方法的调用标识符必须为函数!')
}
var self = this,
args = Array.prototype.slice.call(arguments, 1),
fBind = function () {
var _args = Array.prototype.slice.call(arguments)
return self.apply(this instanceof fBind ? this : ctx, args.concat(_args))
}
fBind.prototype = Object.create(this.prototype)
return fBind
}
}