JS基础(2)——手写数组原型函数 之 不改变原数组(filter,find,findIndex,some,every,map,forEach,reduce)
1、模板
Array.prototype.myFunction = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
// 具体的code
// callback.call(thisArg, this[i], i, this)
// callback函数的调用形式
return res;
}
后面部分代码省略通用部分
2、Array.prototype.filter
参数 callback(element,index,array) thisArg
返回值:新数组
(1)转化为对象,遍历对象
Array.prototype.myFilter = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
// 下列代码可替换
const res = [];
// 让Obj成为回调函数的对象传递(强制转换对象)
const Obj = Object(this);
// >>>0 保证len为number,且为正整数
const len = Obj.length >>> 0;
for(let i = 0;i < len; i++){
// 检查i是否在Obj的属性(会检查原型链)
if(i in Obj){
// 回调函数调用传参
if(callback.call(thisArg, Obj[i], i, Obj)){
res.push(Obj[i]);
}
}
}
return res;
}
什么时候this会是undefined?
(2)数组本身+for循环
Array.prototype.myFilter2 = function(callback, context){
// code同上
const len = this.length,
res = [];
for(let i = 0; i < len; i++){
if(callback.call(context, this[i], i, this)){
res.push(this[i]);
}
}
return res;
}
(3)用forEach
Array.prototype.myFilter3 = function(callback,context) {
// code同上
const res = [];
this.forEach((item, index) => {
if(callback.call(context, item, index, this)){
res.push(item);
}
})
return res;
}
3、Array.prototype.find
find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
注意:1,返回第一个满足要求的值,否则返回undefined。2,不改变原数组
语法:arr.find(callback[, thisArg]);
Array.prototype.myFind = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const Obj = Object(this),
len = Obj.length;
for (let i = 0; i < len; i++){
if(fn.call(thisArg, Obj[i], i, this)){
return Obj[i];
}
}
return undefined;
}
4、Array.prototype.findIndex
findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。
注意:1,返回第一个满足要求的索引,否则返回-1。2,不改变原数组
语法:arr.find(callback[, thisArg]);
Array.prototype.myFindIndex = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const Obj = Object(this),
len = Obj.length;
for (let i = 0; i < len; i++){
if(fn.call(thisArg, Obj[i], i, this)){
return i;
}
}
return -1;
}
5、Array.prototype.some
返回值:若数组中存在元素,满足提供的测试函数,则返回true。否则返回false。
注意:不改变原数组
语法:arr.find(callback[, thisArg]);
Array.prototype.mySome = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const Obj = Object(this),
len = Obj.length;
for (let i = 0; i < len; i++){
if(fn.call(thisArg, Obj[i], i, this)){
return true;
}
}
return false;
}
6、Array.prototype.every
返回值:若数组中每个元素,都满足提供的测试函数,则返回true。否则返回false。
注意:不改变原数组
语法:arr.find(callback[, thisArg]);
Array.prototype.myEvery = function(callback, thisArg) {
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const Obj = Object(this),
len = Obj.length;
for (let i = 0; i < len; i++){
if(!fn.call(thisArg, Obj[i], i, this)){
return false;
}
}
return true;
}
7、Array.prototype.map
参数 callback(currentValue,index,array) thisArg
返回值 原数组
Array.prototype.myMap = function(callback, thisArg){
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function'){
throw new TypeError(callback + ',callback is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const res = [],
len = this.length;
for(let i = 0; i < len; i++){
const cur = callback.call(thisArg, this[i], i, this);
res.push(cur);
}
return res;
}
Array.prototype.map = function(callback, thisArg) {
// code同上
const res = [],
Obj = Object(this),
len = Obj.length >>> 0;
for(let i = 0;i < len; i++){
if(i in Obj){
res[i] = callback.call(thisArg, Obj[i], i, this);
}
}
return res;
}
8、Array.prototype.forEach
参数 callback(currentValue,index,array) thisArg
返回值 undefined
Array.prototype.forEach = function(callback, thisArg) {
if(this == null){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function') {
throw new TypeError(callback + 'is not a function');
}
if (!Array.isArray(this)) {
throw new TypeError(this + ' is not an Array');
}
thisArg = thisArg || this;
const Obj = Object(this),
len = Obj.length >>> 0;
for(let k = 0; k < len; k++){
if(k in Obj){
callback.call(thisArg, Obj[k], k, Obj);
}
}
}
9、Array.prototype.reduce
参数 callback(accumulator,currentValue,index,array) initialValue
返回值 函数累计处理的结果
Array.prototype.myReduce1 = function(callback, initialValue){
if(this == undefined){
throw new TypeError('this is null or not defined');
}
if(typeof callback !== 'function'){
throw new TypeError(callback + ', callback is not a function');
}
if(!Array.isArray(this)){
throw new TypeError(this + ' is not an Array');
}
const obj = Object(this),
len = obj.length >>> 0;
let accumulator = initialValue,
k = 0;
if(accumulator == undefined){
while(k < len && !k in obj){
k++;
}
if(k >= len){
throw new TypeError('Reduce of empty array with no initial value');
}
accumulator = obj[k++];
}
while(k < len){
if(k in obj){
accumulator = callback.call(undefined, accumulator, obj[k], k, obj);
}
k++;
}
return accumulator;
}
Array.prototype.myReduce1 = function(callback, initialValue){
// code同上
const len = this.length;
if(len <= 0){
throw new TypeError('Reduce of empty array with no initial value');
}
let i = 0;
let accumulator = initialValue || this[i++];
while(i < len){
accumulator = callback.call(undefined, accumulator, this[i], i, this);
i++;
}
return accumulator;
}