mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-05-24 13:38:35 +08:00
feat(angular.forEach): add the array/object as the 3rd param like the native array forEach
Closes #7902
This commit is contained in:
@@ -210,9 +210,9 @@ function isArrayLike(obj) {
|
||||
*
|
||||
* @description
|
||||
* Invokes the `iterator` function once for each item in `obj` collection, which can be either an
|
||||
* object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
|
||||
* is the value of an object property or an array element and `key` is the object property key or
|
||||
* array element index. Specifying a `context` for the function is optional.
|
||||
* object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
|
||||
* is the value of an object property or an array element, `key` is the object property key or
|
||||
* array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
|
||||
*
|
||||
* It is worth noting that `.forEach` does not iterate over inherited properties because it filters
|
||||
* using the `hasOwnProperty` method.
|
||||
@@ -240,22 +240,22 @@ function forEach(obj, iterator, context) {
|
||||
// Need to check if hasOwnProperty exists,
|
||||
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
|
||||
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
|
||||
iterator.call(context, obj[key], key);
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
}
|
||||
} else if (isArray(obj) || isArrayLike(obj)) {
|
||||
var isPrimitive = typeof obj !== 'object';
|
||||
for (key = 0, length = obj.length; key < length; key++) {
|
||||
if (isPrimitive || key in obj) {
|
||||
iterator.call(context, obj[key], key);
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
}
|
||||
} else if (obj.forEach && obj.forEach !== forEach) {
|
||||
obj.forEach(iterator, context);
|
||||
obj.forEach(iterator, context, obj);
|
||||
} else {
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
iterator.call(context, obj[key], key);
|
||||
iterator.call(context, obj[key], key, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,10 +654,79 @@ describe('angular', function() {
|
||||
var log = [];
|
||||
var collection = [];
|
||||
collection[5] = 'SPARSE';
|
||||
forEach(collection, function (item, index) { log.push(item + index); });
|
||||
forEach(collection, function (item, index) {
|
||||
log.push(item + index);
|
||||
});
|
||||
expect(log.length).toBe(1);
|
||||
expect(log[0]).toBe('SPARSE5');
|
||||
});
|
||||
|
||||
|
||||
describe('ES spec api compliance', function() {
|
||||
|
||||
function testForEachSpec(expectedSize, collection) {
|
||||
var that = {};
|
||||
|
||||
forEach(collection, function(value, key, collectionArg) {
|
||||
expect(collectionArg).toBe(collection);
|
||||
expect(collectionArg[key]).toBe(value);
|
||||
|
||||
expect(this).toBe(that);
|
||||
|
||||
expectedSize--;
|
||||
}, that);
|
||||
|
||||
expect(expectedSize).toBe(0);
|
||||
}
|
||||
|
||||
|
||||
it('should follow the ES spec when called with array', function() {
|
||||
testForEachSpec(2, [1,2]);
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with arguments', function() {
|
||||
testForEachSpec(2, (function(){ return arguments; }(1,2)));
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with string', function() {
|
||||
testForEachSpec(2, '12');
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with jQuery/jqLite', function() {
|
||||
testForEachSpec(2, jqLite("<span>a</span><span>b</span>"));
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with childNodes NodeList', function() {
|
||||
testForEachSpec(2, jqLite("<p><span>a</span><span>b</span></p>")[0].childNodes);
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with getElementsByTagName HTMLCollection', function() {
|
||||
testForEachSpec(2, jqLite("<p><span>a</span><span>b</span></p>")[0].getElementsByTagName("*"));
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with querySelectorAll HTMLCollection', function() {
|
||||
testForEachSpec(2, jqLite("<p><span>a</span><span>b</span></p>")[0].querySelectorAll("*"));
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with JSON', function() {
|
||||
testForEachSpec(2, {a: 1, b: 2});
|
||||
});
|
||||
|
||||
|
||||
it('should follow the ES spec when called with function', function() {
|
||||
function f(){}
|
||||
f.a = 1;
|
||||
f.b = 2;
|
||||
testForEachSpec(2, f);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user