1.实现bind()
ECMAScript3版本的Function.bind()方法。——来自《JavaScript权威指南》 P191
if(!Function.prototype.bind) {
Function.prototype.bind = function(o /* , args */) {
// 将this和arguments的值保存至变量中以便在后面嵌套的函数中可以使用它们
var self = this, boundArgs = arguments;
// bind()方法的返回值是一个函数
return function() {
// 创建一个实参列表,将传入bind()的第二个及后续的实参都传入这个函数
var i, args = [];
for(i = 1; i < boundArgs.length; i++){ args.push(boundArgs[i]) }
for(i = 0; i < arguments.length; i++){ args.push(arguments[i]) }
// 现在将self作为o的方法来调用,传入这些实参
return self.apply(o, args)
}
}
}
2.实现map()
*Array.prototype.map()
*返回一个由回调函数的返回值组成的新数组
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
// 参数callback:生成新数组元素的函数,
// 使用三个参数-
// currentValue:callback数组中正在处理的当前元素;
// index: 可选。callback数组中正在处理的当前元素的索引;
// array:可选。callbackmap 方法被调用的数组。
// 参数thisArg:可选。执行 callback 函数时使用的this值。如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this都会指向 thisArg参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null或undefined,则 this 指向全局对象 。
ECMAScript3自定义map()——来自来自《JavaScript权威指南》 P195
// 对于每个数组元素调用函数f(),并返回一个结果数组
var map = Array.prototype.map // 如果Array.prototype.map定义了的话就使用这个方法
? function(a,f) {return a.map(f)} // 如果已经存在map方法,就直接使用它
: function(a,f) { // 否则自己实现一个
var results = [];
for (var i = 0, len = a.length; i < len; i++) {
if (i in a) results[i] = f.call(null, a[i], i, a)
}
return results;
};
3.实现reduce()
Array.prototype.reduce()
*从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
// 参数callback:执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,包含四个参数-
// accumulator:累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue;
// currentValue:数组中正在处理的元素;
// index:可选。数组中正在处理的当前元素的索引。如果提供了initialValue,则起始索引号为0,否则从索引1起始;
// array:可选。调用reduce()的数组。
// 参数initialValue:可选。
// 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。
// 在没有初始值的空数组上调用 reduce 将报错。
// 返回值:函数累计处理的结果。
ECMAScript3自定义reduce()——来自来自《JavaScript权威指南》 P195
// 使用函数f()和可选的初始值将数组a减至一个值
var reduce = Array.prototype.reduce // 如果Array.prototype.reduce存在的话,就使用这个方法
? function(a, f, initial) { // 如果reduce()方法存在的话
if (arguments.length > 2) {
return a.reduce(f, initial); // 如果传入了一个初始值
} else {
return a.reduce(f) // 否则没有初始值
}
}
: function(a, f, initial) { // 这个算法来自ES5规范
var i = 0, len = a.length, accumulator;
if (arguments.length > 2) accumulator = initial; // 以特定的初始值开始,否则第一个值取自a
else { // 找到数组中第一个已定义的索引
if (len == 0) throw TypeError();
while (i < len) {
if (i in a) {
accumulator = a[i++];
break;
}
else i++;
}
if (i == len) throw TypeError();
}
// 对于数组中剩下的元素依次调用f()
while (i < len) {
if (i in a) { accumulator = f.call(undefined, accumulator, a[i], i, a)};
i++;
}
return accumulator;
}
4.实现call()
Function.prototype.call()
在一个对象的上下文中应用另一个对象的方法;参数能够以列表形式传入。
Function.prototype.myCall = function() {
if (typeof this !== 'function') throw new Error('Must call with a function')
var realThis = arguments[0] || window;
var realArgs = [...arguments].slice(1);
realThis.func1 = this; // 此this是原方法,保存到传入的第一个参数上
// 用传入的参数来调方法,方法里的this就是传入的参数了
var result = realThis.func1(...realArgs)
delete realThis.func1 // 最后删掉临时存储的原方法
return result // 将执行的返回值返回
}
5.实现apply()
Function.prototype.apply()
在一个对象的上下文中应用另一个对象的方法;参数能够以数组形式传入。
Function.prototype.myApply = function() {
if (typeof this !== 'function') throw new Error('Must call with a function')
var realThis = arguments[0] || window;
var realArgs = arguments[1]; // 直接取第二个参数,是一个数组
realThis.func1 = this; // 此this是原方法,保存到传入的第一个参数上
// 用传入的参数来调方法,方法里的this就是传入的参数了
var result = realThis.func1(...realArgs)
delete realThis.func1
return result
}
本文引用:
JavaScript权威指南(第6版) (豆瓣)book.douban.com