-
Notifications
You must be signed in to change notification settings - Fork 20.6k
Investigate implementing jQuery (specifically .init) as an Array subclass #1754
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
Comments
Comment author: dmethvin It won't work in oldIE, at least. The .length property is squirrely; jeresig tried it around 1.1 timeframe and bailed. @rwaldron wasn't this something still being refined by TC39 for ES6? |
Comment author: rwaldron Replying to dmethvin:
In ES6, it will be as simple as: class jQuery extends Array { constructor(selector, context = document) { super(); // this is now a legit subclass of Array. } // ... implement jQuery prototype methods here }
The issue of course is that new subclass semantics can't be "polyfilled" or "ported" to traditional function declaration/expression syntax, because "super" can't be reserved in a function body. While jQuery was actually quite vocal in the design and specification of this mechanism, we did so understanding that jQuery-the-code wouldn't benefit from real subclassing of builtins for some time. As far as hackish cases like Zepto, proto is never going to be officially standardized, as it has been sent to die in an annex. Instead, Object.setPrototypeOf will compliment Object.getPrototypeOf. |
Comment author: gibson042 I'm petty sure I already solved the oldIE length issues in the jsperf by accepting immutability on existing instances (which doesn't change any current API promises), but I'll look into it more later. This is mostly just a focal point for link aggregation until and unless it gets to an actual pull request. |
Comment author: rwaldron Replying to gibson042:
There are actually 2 length related issues:
Compare the following programs: var a = new Array(1, 2, 3, 4); console.log( a ); // [ 1, 2, 3, 4 ] a.length = 10; console.log( a ); // [ 1, 2, 3, 4, , , , , , ] console.log( a.length ); // 10 a.length = 2; console.log( a ); // [ 1, 2 ] console.log( a.length ); // 2 vs. function List() { Array.call(this); this.push.apply(this, arguments); } List.prototype = Object.create(Array.prototype, { constructor: { value: List } }); var l = new List(1, 2, 3, 4); console.log( l ); // [ 1, 2, 3, 4 ] l.length = 10; console.log( l ); // [ 1, 2, 3, 4 ] console.log( l.length ); // 10 l.length = 2; console.log( l ); // [ 1, 2, 3, 4 ] console.log( l.length ); // 2 This behaviour will be broken with __proto__ as well: function List() { this.__proto__ = Array.prototype; this.push.apply(this, arguments); } var l = new List(1, 2, 3, 4); console.log( l ); // [ 1, 2, 3, 4 ] l.length = 10; console.log( l ); // [ 1, 2, 3, 4 ] console.log( l.length ); // 10 l.length = 2; console.log( l ); // [ 1, 2, 3, 4 ] console.log( l.length ); // 2 And of course, the latter version won't work in browsers that don't support proto. Unrelated to those specific issues, I think inheriting from Array will create a lot of confusing API quirks. Consider the following:
|
Comment author: scott.gonzalez I'm not sure how any of these problems are relevant. As gibson042 already said, this "doesn't change any current API promises". Nobody is doing var divs = $( "div" ); divs.length = 10; And it doesn't matter if our methods are incompatible with Array.prototype methods, unless the incompatibility will actually break things. |
Comment author: dmethvin I'm not seeing the perf benefit, strange. http://wnd8.com/grab/c42af8.png |
Comment author: rwaldron Replying to scott.gonzalez:
They are exactly relevant to these two statements: "The .length property is squirrely; " - dmethvin "I already solved the oldIE length issues in the jsperf by accepting immutability on existing instances" - gibson042
I agree, I'm sure they aren't—but I didn't say any was, I was just trying to thoroughly illustrate the "length problems".
I'm not saying it will break extant code, I'm saying that the behaviour could create confusion. |
Comment author: gibson042 To be clear, I'm interested in performance improvement and size reduction. We've never recommended that anyone set .length (or documented the effects of doing so), and we generally can't expose Array methods because our patterns are to accept selectors in place of elements and pushStack new instances instead of mutating context. Nor will we make new promises like Object.prototype.toString( jQuery() ) === "[object Array]"... this is exclusively about seeking more efficient techniques for implementing our extant API. |
Comment author: rwaldron Replying to gibson042:
Yes, I thought I made it clear that this was understood? http://bugs.jquery.com/ticket/14411?replyto=9#comment:8 My point is that once we say "jQuery is now subclassed from Array", developers will expect these things to work like they do with arrays.
They will be exposed by default and developers will use them. Unless you plan to keep a blacklist of methods to delete? jQuery instance objects will become instanceof Array as well. I promise I'm not trying to rain on your parade, these are just real things to consider. |
Comment author: gibson042 Replying to rwaldron:
We never have to crow about that, and we can continue chastising everyone who tries to take advantage of undocumented implementation details like we currently do with jQuery.support and jQuery.data.
Yep, and I'm actually with you. Changing our prototype chain would be a huge deal... but it might be worthwhile. |
Moving to Roadmap. |
Originally reported by gibson042 at: http://bugs.jquery.com/ticket/14411
Inspired by an interesting Zepto proposal that seems to have legs for us: http://jsperf.com/jquery-prototype-array/4
I suspect that it could reduce size as well, especially in 2.x.
Issue reported for jQuery 1.10.2
The text was updated successfully, but these errors were encountered: