Array.prototype.forEach = function forEach(callback, thisArg) { var T, k; if (this == null) { throw new TypeError("this is null or not defined"); }
// 1. Let O be the result of calling ToObject passing the |this| value as the argument. // 将当前this对象作为参数传递给Obejct对象,返回一个与给定值对应类型的对象。该对象包装了给定的参数。 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). // 进行无符号位移运算符,将所有非数值转换成0,所有大于等于0数取整数部分,并赋值变量len var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception. // See: http://es5.github.com/#x9.11 if (typeof callback !== "function") { throw new TypeError(callback + " is not a function"); }
// 5. If thisArg was supplied, let T be thisArg; elselet T be undefined. // 检查arguments对象是否有第二个参数,如果有则进行操作。 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 /* * a. in运算符希望它的左操作数是一个字符串或可以转换为字符串; * 希望他的右操作数是一个对象; * 如果右侧对象拥有一个名为左操作数值的属性名,那么表达式返回true * b. 对于数组属性需要指定数字形式的索引值来表示数组的属性名称(固有属性除外,如length) * var arr =['a','b','c']; * 0 in arr; => 返回:true * 3 in arr; => 返回:false */ if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk. // 获取值对应赋给给变量kValue 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. // 使用call方法,T(传进的对象),kValue(当前值),k(索引),O(理解为使用的数组) callback.call(T, kValue, k, O); } // d. Increase k by 1. k++; } // 8. return undefined }; }
if (!Array.prototype.map) { Array.prototype.map = function(callback, thisArg) {
var T, A, k;
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;
// 3.如果callback不是函数,则抛出TypeError异常. if (Object.prototype.toString.call(callback) != "[object Function]") { throw new TypeError(callback + " is not a function"); }
// 4. 如果参数thisArg有值,则将T赋值为thisArg;否则T为undefined. if (thisArg) { T = thisArg; }
if (this === void 0 || this === null) throw new TypeError();
var t = Object(this); var len = t.length >>> 0; if (typeof fun !== "function") throw new TypeError();
var res = []; var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0; i < len; i++) { if (i in t) { var val = t[i];
// NOTE: Technically this should Object.defineProperty at // the next index, as push can be affected by // properties on Object.prototype and Array.prototype. // But that method's new, and collisions should be // rare, so use the more-compatible alternative. if (fun.call(thisArg, val, i, t)) res.push(val); } } return res; }; }
if ('function' !== typeof Array.prototype.reduce) { Array.prototype.reduce = function(callback, opt_initialValue) { 'use strict'; if (null === this || 'undefined' === typeof this) { // At the moment all modern browsers, that support strict mode, have // native implementation of Array.prototype.reduce. For instance, IE8 // does not support strict mode, so this check is actually useless. throw new TypeError( 'Array.prototype.reduce called on null or undefined'); } if ('function' !== typeof callback) { throw new TypeError(callback + ' is not a function'); } var index, value, length = this.length >>> 0, isValueSet = false; if (1 < arguments.length) { value = opt_initialValue; isValueSet = true; } for (index = 0; length > index; ++index) { if (this.hasOwnProperty(index)) { if (isValueSet) { value = callback(value, this[index], index, this); } else { value = this[index]; isValueSet = true; } } } if (!isValueSet) { throw new TypeError('Reduce of empty array with no initial value'); } return value; }; }
if ('function' !== typeof Array.prototype.reduceRight) { Array.prototype.reduceRight = function(callback /*, initialValue*/ ) { 'use strict'; if (null === this || 'undefined' === typeof this) { throw new TypeError( 'Array.prototype.reduce called on null or undefined'); } if ('function' !== typeof callback) { throw new TypeError(callback + ' is not a function'); } var t = Object(this), len = t.length >>> 0, k = len - 1, value; if (arguments.length >= 2) { value = arguments[1]; } else { while (k >= 0 && !k in t) k--; if (k < 0) throw new TypeError('Reduce of empty array with no initial value'); value = t[k--]; } for (; k >= 0; k--) { if (k in t) { value = callback(value, t[k], k, t); } } return value; }; }
if (this === void 0 || this === null) throw new TypeError();
var t = Object(this); var len = t.length >>> 0; if (typeof fun !== 'function') throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0; i < len; i++) { if (i in t && fun.call(thisArg, t[i], i, t)) returntrue; }
if (this === void 0 || this === null) throw new TypeError();
var t = Object(this); var len = t.length >>> 0; if (typeof fun !== 'function') throw new TypeError();
var thisArg = arguments.length >= 2 ? arguments[1] : void 0; for (var i = 0; i < len; i++) { if (i in t && !fun.call(thisArg, t[i], i, t)) returnfalse; }
if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(searchElement, fromIndex) { var k; if (this == null) { throw new TypeError('"this" is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if (len === 0) { return -1; } var n = +fromIndex || 0; if (Math.abs(n) === Infinity) { n = 0; } if (n >= len) { return -1; } k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); while (k < len) { if (k in O && O[k] === searchElement) { return k; } k++; } return -1; }; }