1
1
/** section: Language, related to: Array
2
2
* $A(iterable) -> Array
3
- *
3
+ *
4
4
* Accepts an array-like collection (anything with numeric indices) and returns
5
5
* its equivalent as an actual [[Array]] object. This method is a convenience
6
6
* alias of [[Array.from]], but is the preferred way of casting to an [[Array]].
7
- *
7
+ *
8
8
* The primary use of [[$A]] is to obtain an actual [[Array]] object based on
9
9
* anything that could pass as an array (e.g. the `NodeList` or
10
10
* `HTMLCollection` objects returned by numerous DOM methods, or the predefined
11
11
* `arguments` reference within your functions).
12
- *
12
+ *
13
13
* The reason you would want an actual [[Array]] is simple:
14
14
* [[Array Prototype extends Array]] to equip it with numerous extra methods,
15
15
* and also mixes in the [[Enumerable]] module, which brings in another
16
16
* boatload of nifty methods. Therefore, in Prototype, actual [[Array]]s trump
17
17
* any other collection type you might otherwise get.
18
- *
18
+ *
19
19
* The conversion performed is rather simple: `null`, `undefined` and `false` become
20
20
* an empty array; any object featuring an explicit `toArray` method (as many Prototype
21
21
* objects do) has it invoked; otherwise, we assume the argument "looks like an array"
22
22
* (e.g. features a `length` property and the `[]` operator), and iterate over its components
23
23
* in the usual way.
24
- *
24
+ *
25
25
* When passed an array, [[$A]] _makes a copy_ of that array and returns it.
26
- *
26
+ *
27
27
* ##### Examples
28
- *
28
+ *
29
29
* The well-known DOM method [`document.getElementsByTagName()`](http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-A6C9094)
30
30
* doesn't return an [[Array]], but a `NodeList` object that implements the basic array
31
31
* "interface." Internet Explorer does not allow us to extend `Enumerable` onto `NodeList.prototype`,
32
32
* so instead we cast the returned `NodeList` to an [[Array]]:
33
- *
33
+ *
34
34
* var paras = $A(document.getElementsByTagName('p'));
35
35
* paras.each(Element.hide);
36
36
* $(paras.last()).show();
37
- *
37
+ *
38
38
* Notice we had to use [[Enumerable#each each]] and [[Element.hide]] because
39
39
* [[$A]] doesn't perform DOM extensions, since the array could contain
40
40
* anything (not just DOM elements). To use the [[Element#hide]] instance
41
41
* method we first must make sure all the target elements are extended:
42
- *
42
+ *
43
43
* $A(document.getElementsByTagName('p')).map(Element.extend).invoke('hide');
44
- *
44
+ *
45
45
* Want to display your arguments easily? [[Array]] features a `join` method, but the `arguments`
46
46
* value that exists in all functions *does not* inherit from [[Array]]. So, the tough
47
47
* way, or the easy way?
48
- *
48
+ *
49
49
* // The hard way...
50
50
* function showArgs() {
51
51
* alert(Array.prototype.join.call(arguments, ', '));
52
52
* }
53
- *
53
+ *
54
54
* // The easy way...
55
55
* function showArgs() {
56
56
* alert($A(arguments).join(', '));
@@ -69,26 +69,26 @@ function $A(iterable) {
69
69
70
70
/** section: Language, related to: Array
71
71
* $w(String) -> Array
72
- *
72
+ *
73
73
* Splits a string into an [[Array]], treating all whitespace as delimiters. Equivalent
74
74
* to Ruby's `%w{foo bar}` or Perl's `qw(foo bar)`.
75
- *
75
+ *
76
76
* This is one of those life-savers for people who just hate commas in literal arrays :-)
77
- *
77
+ *
78
78
* ### Examples
79
- *
79
+ *
80
80
* $w('apples bananas kiwis')
81
81
* // -> ['apples', 'bananas', 'kiwis']
82
- *
82
+ *
83
83
* This can slightly shorten code when writing simple iterations:
84
- *
84
+ *
85
85
* $w('apples bananas kiwis').each(function(fruit){
86
86
* var message = 'I like ' + fruit
87
87
* // do something with the message
88
88
* })
89
- *
89
+ *
90
90
* This also becomes sweet when combined with [[Element]] functions:
91
- *
91
+ *
92
92
* $w('ads navbar funkyLinks').each(Element.hide);
93
93
**/
94
94
@@ -195,7 +195,7 @@ Array.from = $A;
195
195
}
196
196
}
197
197
if ( ! _each ) _each = each ;
198
-
198
+
199
199
/**
200
200
* Array#clear() -> Array
201
201
*
@@ -430,10 +430,10 @@ Array.from = $A;
430
430
**/
431
431
function indexOf ( item , i ) {
432
432
if ( this == null ) throw new TypeError ( ) ;
433
-
433
+
434
434
var array = Object ( this ) , length = array . length >>> 0 ;
435
435
if ( length === 0 ) return - 1 ;
436
-
436
+
437
437
// The rules for the `fromIndex` argument are tricky. Let's follow the
438
438
// spec line-by-line.
439
439
i = Number ( i ) ;
@@ -443,11 +443,11 @@ Array.from = $A;
443
443
// Equivalent to ES5's `ToInteger` operation.
444
444
i = ( i > 0 ? 1 : - 1 ) * Math . floor ( Math . abs ( i ) ) ;
445
445
}
446
-
446
+
447
447
// If the search index is greater than the length of the array,
448
448
// return -1.
449
449
if ( i > length ) return - 1 ;
450
-
450
+
451
451
// If the search index is negative, take its absolute value, subtract it
452
452
// from the length, and make that the new search index. If it's still
453
453
// negative, make it 0.
@@ -456,7 +456,7 @@ Array.from = $A;
456
456
if ( k in array && array [ k ] === item ) return k ;
457
457
return - 1 ;
458
458
}
459
-
459
+
460
460
461
461
/** related to: Array#indexOf
462
462
* Array#lastIndexOf(item[, offset]) -> Number
@@ -466,7 +466,7 @@ Array.from = $A;
466
466
*
467
467
* Returns the position of the last occurrence of `item` within the
468
468
* array — or `-1` if `item` doesn't exist in the array.
469
- *
469
+ *
470
470
* `Array#lastIndexOf` acts as an ECMAScript 5 [polyfill](http://remysharp.com/2010/10/08/what-is-a-polyfill/).
471
471
* It is only defined if not already present in the user's browser, and it
472
472
* is meant to behave like the native version as much as possible. Consult
@@ -475,10 +475,10 @@ Array.from = $A;
475
475
**/
476
476
function lastIndexOf ( item , i ) {
477
477
if ( this == null ) throw new TypeError ( ) ;
478
-
478
+
479
479
var array = Object ( this ) , length = array . length >>> 0 ;
480
480
if ( length === 0 ) return - 1 ;
481
-
481
+
482
482
// The rules for the `fromIndex` argument are tricky. Let's follow the
483
483
// spec line-by-line.
484
484
if ( ! Object . isUndefined ( i ) ) {
@@ -492,7 +492,7 @@ Array.from = $A;
492
492
} else {
493
493
i = length ;
494
494
}
495
-
495
+
496
496
// If fromIndex is positive, clamp it to the last index in the array;
497
497
// if it's negative, subtract its absolute value from the array's length.
498
498
var k = i >= 0 ? Math . min ( i , length - 1 ) :
@@ -526,22 +526,22 @@ Array.from = $A;
526
526
array . length = n ;
527
527
return array ;
528
528
}
529
-
529
+
530
530
// Certain ES5 array methods have the same names as Prototype array methods
531
531
// and perform the same functions.
532
532
//
533
533
// Prototype's implementations of these methods differ from the ES5 spec in
534
- // the way a missing iterator function is handled. Prototype uses
534
+ // the way a missing iterator function is handled. Prototype uses
535
535
// `Prototype.K` as a default iterator, while ES5 specifies that a
536
- // `TypeError` must be thrown. Implementing the ES5 spec completely would
536
+ // `TypeError` must be thrown. Implementing the ES5 spec completely would
537
537
// break backward compatibility and would force users to pass `Prototype.K`
538
- // manually.
538
+ // manually.
539
539
//
540
540
// Instead, if native versions of these methods exist, we wrap the existing
541
541
// methods with our own behavior. This has very little performance impact.
542
542
// It violates the spec by suppressing `TypeError`s for certain methods,
543
543
// but that's an acceptable trade-off.
544
-
544
+
545
545
function wrapNative ( method ) {
546
546
return function ( ) {
547
547
if ( arguments . length === 0 ) {
@@ -559,15 +559,15 @@ Array.from = $A;
559
559
}
560
560
} ;
561
561
}
562
-
562
+
563
563
// Note that #map, #filter, #some, and #every take some extra steps for
564
564
// ES5 compliance: the context in which they're called is coerced to an
565
565
// object, and that object's `length` property is coerced to a finite
566
566
// integer. This makes it easier to use the methods as generics.
567
567
//
568
568
// This means that they behave a little differently from other methods in
569
569
// `Enumerable`/`Array` that don't collide with ES5, but that's OK.
570
-
570
+
571
571
/**
572
572
* Array#map([iterator = Prototype.K[, context]]) -> Array
573
573
* - iterator (Function): The iterator function to apply to each element
@@ -601,11 +601,11 @@ Array.from = $A;
601
601
results . length = n ;
602
602
return results ;
603
603
}
604
-
604
+
605
605
if ( arrayProto . map ) {
606
606
map = wrapNative ( Array . prototype . map ) ;
607
607
}
608
-
608
+
609
609
/**
610
610
* Array#filter(iterator[, context]) -> Array
611
611
* - iterator (Function): An iterator function to use to test the
@@ -625,7 +625,7 @@ Array.from = $A;
625
625
function filter ( iterator ) {
626
626
if ( this == null || ! Object . isFunction ( iterator ) )
627
627
throw new TypeError ( ) ;
628
-
628
+
629
629
var object = Object ( this ) ;
630
630
var results = [ ] , context = arguments [ 1 ] , value ;
631
631
@@ -674,15 +674,14 @@ Array.from = $A;
674
674
return true ;
675
675
}
676
676
}
677
-
677
+
678
678
return false ;
679
679
}
680
-
680
+
681
681
if ( arrayProto . some ) {
682
- var some = wrapNative ( Array . prototype . some ) ;
682
+ some = wrapNative ( Array . prototype . some ) ;
683
683
}
684
-
685
-
684
+
686
685
/**
687
686
* Array#every([iterator = Prototype.K[, context]]) -> Boolean
688
687
* - iterator (Function): An optional function to use to evaluate each
@@ -699,7 +698,7 @@ Array.from = $A;
699
698
* is meant to behave like the native version as much as possible. Consult
700
699
* the [ES5 specification](http://es5.github.com/#x15.4.4.16) for more
701
700
* information.
702
- *
701
+ *
703
702
**/
704
703
function every ( iterator ) {
705
704
if ( this == null ) throw new TypeError ( ) ;
@@ -712,27 +711,34 @@ Array.from = $A;
712
711
return false ;
713
712
}
714
713
}
715
-
714
+
716
715
return true ;
717
716
}
718
-
717
+
719
718
if ( arrayProto . every ) {
720
- var every = wrapNative ( Array . prototype . every ) ;
719
+ every = wrapNative ( Array . prototype . every ) ;
721
720
}
722
-
721
+
723
722
// We used to define an `inject` method here that relied on ES5's
724
723
// `Array#reduce` (if present), but using `reduce` prevents us from
725
724
// catching a thrown `$break`. So arrays now use the standard
726
725
// `Enumerable.inject` like they did previously.
727
-
726
+
728
727
Object . extend ( arrayProto , Enumerable ) ;
729
728
729
+ // Enumerable's `entries` method is no longer safe to mixin to arrays, as
730
+ // it conflicts with an ES6 method. But it can still be mixed into other
731
+ // things.
732
+ if ( arrayProto . entries === Enumerable . entries ) {
733
+ delete arrayProto . entries ;
734
+ }
735
+
730
736
if ( ! arrayProto . _reverse )
731
737
arrayProto . _reverse = arrayProto . reverse ;
732
738
733
739
Object . extend ( arrayProto , {
734
740
_each : _each ,
735
-
741
+
736
742
map : map ,
737
743
collect : map ,
738
744
select : filter ,
@@ -742,7 +748,7 @@ Array.from = $A;
742
748
any : some ,
743
749
every : every ,
744
750
all : every ,
745
-
751
+
746
752
clear : clear ,
747
753
first : first ,
748
754
last : last ,
0 commit comments