3 ms·
No, there aren't two callable types in JavaScript. Thats precisely the point. Every single function has a `this` argument: function f() { return this + 5; }
by spion 9y ago
No, there aren't two callable types in JavaScript. Thats precisely the point. Every single function has a `this` argument:
function f() { return this + 5; }
But there are only two ways to call it:
f.call(5) // calls with `this` argument set to 5
and
let x = new Number(5)
x.f = f;
x.f(); // syntax sugar for to x.f.call(x)
The confusing part here is that `x.f()` is very different from `x.f`, and is most definitely NOT the same as `(x.f)()`, but more of an `(x.f).call(x)` Other than that and the fact that the argument is always there even if you don't specify it, its exactly the same as Lua, metatables (prototypes) and all.
To resolve this confusion once and for all, we desperately need the bind operator [1] to provide a primitive on top of which the rest can be explained.
[1]: https://github.com/tc39/proposal-bind-operator https://github.com/tc39/proposal-bind-operator
- nybble41 9y ago> No, there aren't two callable types in JavaScript. Thats precisely the point. Yes, that _was_ precisely the point. Even though "methods" which require a context and "functions" which do not are logically two distinct types, JavaScript treats them as the same: 'this' is always present in some form. Then, since many (most?) functions _don't_ actually require a context, it allows "methods" to be called without an explicit value for 'this', which amounts to leaving out a parameter. Except that this particular parameter has a confusing default which depends on the context in which the call occurs. Contrast this with other languages where the equivalent of 'this' is either included in the function's argument list or available only to code with a special "method" type which must be called with an explicit context. > The confusing part here is that `x.f()` is very different from `x.f`, and is most definitely NOT the same as `(x.f)()`, but more of an `(x.f).call(x)` Yes, exactly. The behavior changes depending on whether "x.f" is treated as a method call ("x.f()") or a plain function call ("(x.f)()"). And yet the only visible difference is putting parentheses around a legal value expression, or assigning the value to a variable or function parameter before calling it. Contrast this with Lua, where the colon/method-call operator is only legal within a function call ("x:f" is a syntax error unless followed by an argument list) and there is no difference between "x.f()" and "(x.f)()". > Other than [the difference between (x.f)() and x.f()] and the fact that the argument is always there even if you don't specify it, its exactly the same as Lua, metatables (prototypes) and all. Agreed, though Lua also has a dedicated "method call" operator which might be considered significant. However, those differences are exactly why the Lua approach is less "magical" and easier to comprehend and work with. The underlying workings are bound to be similar since they are both Turing-complete dynamically-typed imperative languages with prototypical object systems.
- spion 9y agoYeah well, it is what it is. Instead of having alternate syntax to pass the first argument, we can at least get first class syntax to pass a custom `this` argument. That will at least allow us to talk about `this` being a function argument, not a special magic "thing" - and there will be just one thing to learn, the big difference between (x.f)() and x.f()