Я пытался написать доказательство концепции для класса, расширяющего Function
, чтобы продемонстрировать конструктор функций, который можно было бы инициализировать на основе другой функции, и отразить this
и arguments
следующим образом:
class Handle extends Function {
constructor(functor) {
super("functor", "slice", '
"use strict";
return functor
.call(this, ...slice.call(arguments, 2));
');
return this.bind(this, functor, Array.prototype.slice)
}
}
let handle = new Handle(function test() {
console.log(this instanceof Handle, arguments.length)
})
console.log(handle instanceof Handle, handle.length)
handle(1, 2, 3)
Тем не менее, я думал, что это приведет к идентичному поведению, основанному на моем понимании call
и apply
:
class Handle extends Function {
constructor(functor) {
super("instance", "call", "slice", '
"use strict";
return call(this, instance, ...slice.call(arguments, 3));
');
return Function.bind
.call(this, functor, this, Function.call, Array.prototype.slice)
}
}
let handle = new Handle(function test() {
console.log(this instanceof Handle, arguments.length)
})
console.log(handle instanceof Handle, handle.length)
handle(1, 2, 3)
Это бросает
Uncaught TypeError: call is not a function
at Function.eval (eval at Handle (js:4), <anonymous>:5:14)
так что что-то не так с функцией call()
. Мое понимание заключалось в том, что если call()
не был частью выражения вызова, его первым аргументом станет вызываемая функция, а остальные аргументы станут контекстом и аргументами функции, вроде Function.call.call(this, instance,...slice.call(arguments, 3))
:
class Handle extends Function {
constructor(functor) {
super("instance", "call", "slice", '
"use strict";
return Function.call.call(this, instance, ...slice.call(arguments, 3));
');
return Function.bind
.call(this, functor, this, Function.call, Array.prototype.slice)
}
}
let handle = new Handle(function test() {
console.log(this instanceof Handle, arguments.length)
})
console.log(handle instanceof Handle, handle.length)
handle(1, 2, 3)
Может кто-то объяснить, что я недопонимаю, или почему это не так?
Uncaught TypeError: call is not a function
так что что-то не так с функцией call().
Обратите внимание, что это сообщение вводит в заблуждение, это не call
который не является функцией, а то, что call
вызов.
Мое понимание заключалось в том, что если call() не был частью выражения вызова, его первым аргументом стала бы вызываемая функция
Нет. Эта функция вызывается не всегда this
контекст call
вызова, и ничего, что меняет это, когда call
не вызывается как метод. Вам нужно сделать call.call(functor, context,...args)
.
call.call(functor, context, ...args)
ли call.call(functor, context, ...args)
functor.call(context, ...args)
?
.call
functor
)
Вы вызываете Function.call
(Function.prototype.call
будет более корректно использовать, я думаю) без this
. Это нужно, хотя, потому что this
значение - это функция, которую он вызывает. Более короткий пример проблемы:
var call = Function.prototype.call;
call();
Может быть, вы задумали call.call(this, …)
?
class Handle extends Function {
constructor(functor) {
super("instance", "call", "slice", '
"use strict";
return call.call(this, instance, ...slice.call(arguments, 3));
');
return Function.bind
.call(this, functor, this, Function.call, Array.prototype.slice)
}
}
let handle = new Handle(function test() {
console.log(this instanceof Handle, arguments.length)
})
console.log(handle instanceof Handle, handle.length)
handle(1, 2, 3)
call.call(...)
? Это была проблема все время? facepalm Но Function.call
и Function.prototype.call
одинаково действительны, поскольку Function instanceof Function
, поэтому он будет иметь call
метода-члена, являющийся экземпляром самого себя.
{}.toString.call
или что-то еще. К счастью, в этом нет необходимости, поскольку вы можете просто использовать свой оригинальный метод.
Function
ExtensibleFunction
основном отбрасывает инстанцируемое свойствоthis
, которое, кажется, обходит проблему, а не решает ее «удовлетворяющим» способом, заключая вас в кавычки.