Reputation: 21291
(I think) I have tried every .bind
, .call()
or .apply
version,
But I can't make F2("World!")
work
var F1 = window["document"]["body"];
// works fine:
F1["append"]("Hello")
var F2 = F1["append"];
// valid function append()
console.log( F2 );
// Illegal invocation
F2("World!");
Would like to get it working in:
let D=["document", "body", "append"];
([0,1,2].reduce((root, x) => root[D[x]], window))('World!');
Upvotes: 3
Views: 153
Reputation: 371193
F1["append"]
is only a reference to Element.prototype.append
:
var F1 = window["document"]["body"];
var F2 = F1["append"];
console.log(F2 === Element.prototype.append);
This function requires a calling context - a this
value - in order for the function to know what the parent element is, to which the child will be appended to. With
F1["append"]("Hello")
The object on which the function is called is F1
, the this
value that the function sees, so everything works as expected. But with
F2("World!");
There is no calling context - the function being called is not called as part of an object, and the function hasn't been bound, so the internal Element.prototype.append
doesn't know which parent element the child should be appended to.
.bind
works, as does .call
, as does making a function which calls F1
with the proper calling context:
var F1 = window["document"]["body"];
// works fine:
F1["append"]("Hello")
var F2 = F1["append"];
F2.call(F1, "World!");
var F1 = window["document"]["body"];
// works fine:
F1["append"]("Hello")
var F2 = child => F1["append"](child);
F2("World!");
To do this with reduce
, first .pop
off the last property. Then use reduce
to get to the next to last property (the object on which the function should be called on). Then you can call the function with the required calling context via bracket notation:
const paths = ["document", "body", "append"];
const fnProp = paths.pop();
const lastObj = paths.reduce((parent, nextProp) => parent[nextProp], window);
lastObj[fnProp]('World');
Upvotes: 2