Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should functions be iterated as arrays? #2830

Closed

Conversation

jgonggrijp
Copy link
Collaborator

@jgonggrijp jgonggrijp commented Mar 16, 2020

@jashkenas The current behaviour, as implemented in the internal isArrayLike function, reflects "yes", based on the fact that functions have a numerical length property within safe bounds. However, I think the answer should be "no", for reasons I'll give below, and the current PR could be used to change the behaviour accordingly.

My case for adding a check against functions and iterating them object-like, rather than array-like, is as follows:

  • Functions do not follow the convention of using length to indicate the number of integer keys. One could argue that this function property should have a different name, such as numArgs.
  • Functions, especially constructors, often have nonnumeric keys that one may want to iterate over. For example _.
  • Functions are common enough that a targeted check may be warranted.

The way isArrayLike arrives at its conclusion has been subject of debate in the past (for example in #1590). Opponents often took the stance that checking for a numerical length property is wrong altogether, sometimes suggesting radical changes in the way Underscore iteration should work. I would like to emphasize that I'm not in that school of thought. To the contrary; I think checking for a numerical length is essentially correct. However, I do think that the length property of functions has the wrong name for what it represents, which means that it should be disregarded when iterating a function.

Edit to add acknowledgement: I found one comment (#1590 (comment)) which suggested the same approach. At the time, it drowned in the heated debate.

@jashkenas
Copy link
Owner

This may be true, but it would be a pretty major breaking change — and isn't something terribly useful. There are already plenty of good and well-understood ways to iterate over the enumerable keys of a function object.

Furthermore, the reason we haven’t done something like this in the past is because of a bit more paranoia and conservatism. There are folks out there who make regular JS objects Array-like, and use them like arrays. There’s nothing stopping you from turning a function into an Array-like object, and redefining length to suit your own purposes accordingly. typeof object === "function" is just not a sufficiently good check to know. That’s why Underscore has kept the "tries to work on anything with a length" policy in the past.

For someone doing this sort of thing in the wild, see: https://stackoverflow.com/questions/11886578/creating-array-like-objects-in-javascript/34729224#34729224

If we were starting from scratch again, we might choose differently.

@jgonggrijp
Copy link
Collaborator Author

There’s nothing stopping you from turning a function into an Array-like object, and redefining length to suit your own purposes accordingly.

I didn't thank of that. Thanks for opening my eyes. I am convinced and will retract the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants