Skip to content

Commit 460be46

Browse files
Further tweaks to array methods for ES5 compatibility.
1 parent bd3965d commit 460be46

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

src/prototype/lang/array.js

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -500,13 +500,23 @@ Array.from = $A;
500500
};
501501
}
502502

503+
// Note that #map, #filter, #some, and #every take some extra steps for
504+
// ES5 compliance: the context in which they're called is coerced to an
505+
// object, and that object's `length` property is coerced to a finite
506+
// integer. This makes it easier to use the methods as generics.
507+
//
508+
// This means that they behave a little differently from other methods in
509+
// `Enumerable`/`Array` that don't collide with ES5, but that's OK.
503510
function map(iterator) {
511+
if (this == null) throw new TypeError();
504512
iterator = iterator || Prototype.K;
513+
514+
var object = Object(this);
505515
var results = [], context = arguments[1], n = 0;
506516

507-
for (var i = 0, length = this.length; i < length; i++) {
508-
if (i in this) {
509-
results[n] = iterator.call(context, this[i], i, this);
517+
for (var i = 0, length = object.length >>> 0; i < length; i++) {
518+
if (i in object) {
519+
results[n] = iterator.call(context, object[i], i, object);
510520
}
511521
n++;
512522
}
@@ -519,14 +529,16 @@ Array.from = $A;
519529
}
520530

521531
function filter(iterator) {
522-
if (!Object.isFunction(iterator))
532+
if (this == null || !Object.isFunction(iterator))
523533
throw new TypeError();
534+
535+
var object = Object(this);
524536
var results = [], context = arguments[1], value;
525537

526-
for (var i = 0, length = this.length; i < length; i++) {
527-
if (i in this) {
528-
value = this[i];
529-
if (iterator.call(context, value, i, this)) {
538+
for (var i = 0, length = object.length >>> 0; i < length; i++) {
539+
if (i in object) {
540+
value = object[i];
541+
if (iterator.call(context, value, i, object)) {
530542
results.push(value);
531543
}
532544
}
@@ -541,11 +553,13 @@ Array.from = $A;
541553
}
542554

543555
function some(iterator) {
556+
if (this == null) throw new TypeError();
544557
iterator = iterator || Prototype.K;
545558
var context = arguments[1];
546559

547-
for (var i = 0, length = this.length; i < length; i++) {
548-
if (i in this && iterator.call(context, this[i], i, this)) {
560+
var object = Object(this);
561+
for (var i = 0, length = object.length >>> 0; i < length; i++) {
562+
if (i in object && iterator.call(context, object[i], i, object)) {
549563
return true;
550564
}
551565
}
@@ -558,11 +572,13 @@ Array.from = $A;
558572
}
559573

560574
function every(iterator) {
575+
if (this == null) throw new TypeError();
561576
iterator = iterator || Prototype.K;
562577
var context = arguments[1];
563578

564-
for (var i = 0, length = this.length; i < length; i++) {
565-
if (i in this && !iterator.call(context, this[i], i, this)) {
579+
var object = Object(this);
580+
for (var i = 0, length = object.length >>> 0; i < length; i++) {
581+
if (i in object && !iterator.call(context, object[i], i, object)) {
566582
return false;
567583
}
568584
}
@@ -579,9 +595,9 @@ Array.from = $A;
579595
function inject(memo, iterator) {
580596
iterator = iterator || Prototype.K;
581597
var context = arguments[2];
582-
// The iterator must be bound, as `Array#reduce` always executes the
583-
// iterator in the global context.
584-
return _reduce.call(this, iterator.bind(context), memo, context);
598+
// The iterator must be bound, as `Array#reduce` always binds to
599+
// `undefined`.
600+
return _reduce.call(this, iterator.bind(context), memo);
585601
}
586602

587603
// Piggyback on `Array#reduce` if it exists; otherwise fall back to the

0 commit comments

Comments
 (0)