2

For example, Array.from is referred to as a method, but Array.isArray, as a function

https://www.ecma-international.org/ecma-262/8.0/index.html#sec-properties-of-the-array-constructor

in practice both are callable as functions (const arrFrom = Array.from; arrFrom('string');), but does the spec guarantee this for all static built-ins or some or none?

stackblow
  • 185
  • 4
  • @mhodges Neither `isArray` nor `from` live on `Array.prototype`. – Bergi Dec 20 '17 at 19:04
  • @Bergi You're right, I misspoke – mhodges Dec 20 '17 at 19:07
  • By **in practice both are callable as functions**, do you mean **both are callable both as method and as function, without an observable difference in effect**? That's a subtle but quite important distinction. – JJWesterkamp Dec 20 '17 at 19:27
  • I meant without difference, but yes, looking at the spec for Array.form, it does switch on `this` so there's going to be some difference/ – stackblow Dec 20 '17 at 21:14

1 Answers1

3

No, there are no guarantees. It's different for every static method.

For any given built-in static method, lookup its specification, and if it does not refer to this, it's a function.

  • Object: none of the static Object methods rely on their receiver, they don't use the Object constructor but just operate on their arguments or create a new plain object.
  • Function, GeneratorFunction, AsyncFunction, Boolean, Errors, RegExp, Map, WeakMap, Set, WeakSet, SharedArrayBuffer, DataView: none of these constructors contains any static methods
  • Symbol: none of the static Symbol methods rely on their receiver, they don't use the Symbol constructor
  • Number, Date: none of their static methods rely on their receiver, they just operate on their arguments and return a primitive number.
  • String: none of the static String methods rely on their receiver, they don't use the String constructor but just operate on their arguments and return a primitive string.
  • Array:
    • isArray just returns a boolean
    • from, of: these do rely on their receiver value, but when it's not a constructor function they fall back on the default Array. This is probably for backwards compatibility to when Array was not extensible.
  • Typed arrays: they don't have static methods on their own, but inherit them from a common intrinsic object
    • from, of: these do rely on their receiver value to be a constructor that returns a typed array
  • ArrayBuffer:
    • isView just returns a boolean
  • Math, Atomics, JSON, Reflect: they're not constructors anyway, their "methods" are just namespaced functions that do not rely on their receiver
  • Promise:
    • all, race, reject, resolve: these do rely on their receiver value to be a constructor that works like Promise
  • Proxy is not really designed to be subclassable, it wouldn't even need to be a constructor.
    • revocable: does not rely on its receiver

So in general most of the static "methods" are just namespaced functions, ignoring their receiver completely. There are however a few methods which return instances of the constructor they are invoked on, most notably promise and (typed) array methods, which do require the respective receiver. Object and Array are exceptions to this.

stackblow
  • 185
  • 4
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • You appear to be saying it's guaranteed for some built-ins and not others, please point to such a guarantee in the spec. – stackblow Dec 20 '17 at 19:11
  • Thanks for the added detail, but where's the spec reference? I am not asking about implementations, nor for an opinion, but a definitive specification of the "methods" being functions. – stackblow Dec 20 '17 at 20:41
  • @Alex You just have to read the spec for the respective function and check whether it uses the `this` value, i.e. whether it's a method or not. – Bergi Dec 20 '17 at 20:42
  • 2
    Ok, so you're saying that if the abstract method description in the spec does not refer to `this` that's a guarantee of it being a function. Makes sense. – stackblow Dec 20 '17 at 21:06