, , , forEach reduce () / ECMA5 ( ), /.
Array.prototype.forEach(callbackfn [, thisArg])
callbackfn , . forEach callbackfn , , . callbackfn ; .
thisArg, callbackfn. , undefined.
callbackfn : , .
forEach , , callbackfn.
, forEach, callbackfn. , forEach, callbackfn. , , , , ; , forEach , .
forEach , :
- O - ToObject, .
- lenValue O [[Get]] "length".
- len - ToUint32 (lenValue).
- IsCallable (callbackfn) , TypeError.
- thisArg , T - Arg; T undefined.
- k 0.
- , k < Len
- Pk - ToString (k).
- kPresent O [[HasProperty]] Pk.
- kPresent ,
- kValue [[Get]] O Pk.
- callbackfn [[Call]] T , kValue, k O.
- k 1.
- undefined.
length forEach 1.
forEach ; , Array. . forEach , .
-
Array.prototype.reduce(callbackfn [, initialValue])
callbackfn , . callback, , , , .
callbackfn : previousValue ( callbackfn), currentValue ( ), currentIndex . previousValue currentValue . initialValue, Value initialValue, currentValue . initialValue , Value , currentValue . TypeError, , initialValue .
reduce , , callbackfn.
, , callbackfn. , , callbackfn. , , callbackfn, , ; , , .
reduce , :
- O - ToObject, .
- lenValue O [[Get]] "length".
- len - ToUint32 (lenValue).
- IsCallable (callbackfn) , TypeError.
- len 0, initialValue , TypeError.
- k 0.
- initialValue,
- initialValue.
- Else, initialValue
- kPresent false.
- , kPresent k < Len
- Pk - ToString (k).
- kPresent O [[HasProperty]] Pk.
- kPresent ,
- [[Get]] O Pk.
- k 1.
- kPresent , TypeError.
- , k < Len
- Pk - ToString (k).
- kPresent O [[HasProperty]] Pk.
- kPresent ,
- kValue [[Get]] O Pk.
- callbackfn [[Call]] undefined , , kValue, k O.
- k 1.
- .
length 1.
; , Array. . , .
( 100% , ) .
function firstToCapital(inputString) {
return inputString.charAt(0).toUpperCase() + inputString.slice(1).toLowerCase();
}
function isClass(inputArg, className) {
return Object.prototype.toString.call(inputArg) === '[object ' + firstToCapital(className) + ']';
}
function checkObjectCoercible(inputArg) {
if (typeof inputArg === 'undefined' || inputArg === null) {
throw new TypeError('Cannot convert argument to object');
}
return inputArg;
};
function ToObject(inputArg) {
checkObjectCoercible(inputArg);
if (isClass(inputArg, 'boolean')) {
inputArg = new Boolean(inputArg);
} else if (isClass(inputArg, 'number')) {
inputArg = new Number(inputArg);
} else if (isClass(inputArg, 'string')) {
inputArg = new String(inputArg);
}
return inputArg;
}
function ToUint32(inputArg) {
return inputArg >>> 0;
}
function throwIfNotAFunction(inputArg) {
if (!isClass(inputArg, 'function')) {
throw TypeError('Argument is not a function');
}
return inputArg;
}
function forEach(array, fn, thisArg) {
var object = ToObject(array),
length,
index;
throwIfNotAFunction(fn);
length = ToUint32(object.length);
for (index = 0; index < length; index += 1) {
if (index in object) {
fn.call(thisArg, object[index], index, object);
}
}
}
function reduce(array, fn, initialValue) {
var object = ToObject(array),
accumulator,
length,
kPresent,
index;
throwIfNotAFunction(fn);
length = ToUint32(object.length);
if (!length && arguments.length === 2) {
throw new TypeError('reduce of empty array with no initial value');
}
index = 0;
if (arguments.length > 2) {
accumulator = initialValue;
} else {
kPresent = false;
while (!kPresent && index < length) {
kPresent = index in object;
if (kPresent) {
accumulator = object[index];
index += 1;
}
}
if (!kPresent) {
throw new TypeError('reduce of empty array with no initial value');
}
}
while (index < length) {
if (index in object) {
accumulator = fn.call(undefined, accumulator, object[index], index, object);
}
index += 1;
}
return accumulator;
}
function keys(object) {
if (!isClass(object, 'object') && !isClass(object, 'function')) {
throw new TypeError('Argument must be an object or function');
}
var props = [],
prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
props.push(prop);
}
}
return props;
}
var inputWords = ['Apple', 'Banana', 'Apple', 'Pear', 'Pear', 'Pear'];
var counts = reduce(inputWords, function (previous, element) {
previous[element] = ++previous[element] || 1;
return previous;
}, {});
forEach(keys(counts), function (key) {
console.log(key, this[key]);
}, counts);
jsFiddle
, , .:)