map 方法和 forEach 方法是数组的两个常用方法;都是对数组的所有元素进行callback处理; map会返回一个新数组, 但是forEach 的返回值是undefined。
map的语法是:
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array }[,
thisArg])
forEach的语法是:
arr.forEach(callback[, thisArg]);
map的实现
Array.prototype.myMap = function (callback, thisArg) {
// thisArg 执行函数时使用的的this
// 3.如果callback不是函数,则抛出TypeError异常.
if (Object.prototype.toString.call(callback) != "[object Function]") { // typeof callback == function
throw new TypeError(callback + " is not a function");
}
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. 将O赋值为调用map方法的数组.
var O = Object(this);
// 2.将len赋值为数组O的长度.
var len = O.length >>> 0;
// 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined.
var T
if (thisArg) {
T = thisArg; // 执行callback函数时使用的this值
}
// 5. 创建新数组A,长度为原数组O长度len
var A = new Array(len);
// 6. 将k赋值为0
var k = 0;
// 7. 当 k < len 时,执行循环. 尽量不用for循环
while (k < len) {
var kValue, mappedValue;
//遍历O,k为原数组索引
if (k in O) {
//kValue为索引k对应的值.
kValue = O[k];
// 执行callback,this指向T,参数有三个.分别是kValue:值,k:索引,O:原数组.
mappedValue = callback.call(T, kValue, k, O);
// 返回值添加到新数组A中.
A[k] = mappedValue;
}
// k自增1
k++;
}
// 8. 返回新数组A
return A;
};
myMap的测试用例
var array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.myMap(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
forEach的实现
Array.prototype.myForEach = function (callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 如果callback 不是函数 抛出异常
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
// 1. Let O be the result of calling toObject() passing the
// |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var len = O.length >>> 0;
// 4. If isCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
// 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
// 既可以 thisArg存在就赋值 或者arguments.length > 1 或者 arguments.length >= 2
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty
// internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
if (!Array.prototype.reduce) {
Object.defineProperty(Array.prototype, 'reduce', {
value: function (callback /*, initialValue*/) {
if (this === null) {
throw new TypeError('Array.prototype.reduce ' +
'called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback +
' is not a function');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// Steps 3, 4, 5, 6, 7
var k = 0;
var value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k < len && !(k in o)) {
k++;
}
// 3. If len is 0 and initialValue is not present,
// throw a TypeError exception.
if (k >= len) {
throw new TypeError('Reduce of empty array ' +
'with no initial value');
}
value = o[k++];
}
// 8. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kPresent be ? HasProperty(O, Pk).
// c. If kPresent is true, then
// i. Let kValue be ? Get(O, Pk).
// ii. Let accumulator be ? Call(
// callbackfn, undefined,
// « accumulator, kValue, k, O »).
if (k in o) {
value = callback(value, o[k], k, o);
}
// d. Increase k by 1.
k++;
}
// 9. Return accumulator.
return value;
}
});
}
myForEach的测试用例:
var array1 = ['a', 'b', 'c'];
array1.myForEach(function(element) {
console.log(element);
});
// expected output: "a"
// expected output: "b"
// expected output: "c"
网友评论