【ES5新特性四】数组新增方法

ES5中新增了很多数组的方法,使用这些方法能够大大减少开发的时间成本,让代码更具有可读性。下面就让我们来看看,都有哪些新增的方法?

原生JavaScipt案例合集
JavaScript +DOM基础
JavaScript 基础到高级
Canvas游戏开发

将这些方法和之前的传统方式处理逻辑做对比、思考,并通过原型尝试拦截去实现这些相关的方法。

1.1 判断数组

  • 第一种方式判断实例化对象

    obj instanceof Array
    
  • 第二种方式判断构造函数

    obj.constructor === Array
    
  • 第三种方式判断对象的类型

    Object.prototype.toString.call(obj)
    
  • 第四种数组的静态方法(ES5新增)

    Array.isArray(obj)
    

代码示例

// instanceof 
console.log(obj instanceof Array); // false
console.log(arr instanceof Array); // true
// 当构造函数是Object的时候也会返回true
console.log(arr instanceof Object); // true

// constructor
console.log(obj.constructor === Array); // fasle
console.log(arr.constructor === Array); // true
console.log(arr.constructor === Object); // false
	
// 判断对象的类型
console.log(Object.prototype.toString.call(obj) === "[object Array]"); // false
console.log(Object.prototype.toString.call(arr) === "[object Array]"); // true
// ES5拓展的静态方法
console.log(Array.isArray(obj)); // false
console.log(Array.isArray(arr)); // true

1.2 获取数组成员的索引

indexOf(item,?startIndex) 返回一个指定的元素在数组中第一次出现的位置

lastIndexOf(item,?startIndex) 返回一个指定的元素在数组中最后出现的位置,从该字符串的后面向前查找

  1. 两个方法使用时,如果要检索的元素没有出现,则返回 -1
  2. 两个方法,如果省略第二个参数,则是从第一个或最后一个索引开始查找。浏览器都支持这两个方法,但是 IE8 及 更早IE版本不支持该方法
  3. 在查找的过程中不会进行类型转换,而是真正的全等查找

代码演示

// 创建一个数组
var arr = ["apple","orange","banana","pear","orange","kiwi fruit","orange","peach"];

// 利用ES5方法获取指定成员第一次和最后一次出现的位置
// indexOf() 返回一个指定的元素在数组中第一次出现的位置
// console.log(arr.indexOf("orange"));//1  不指定起始索引,默认从0开始
// console.log(arr.indexOf("orange",2));//4 从第2个索引开始向后查找
// lastIndexOf()  返回一个指定的元素在数组中最后出现的位置
// console.log(arr.lastIndexOf("orange"));//6  不指定索引,默认从最后一个开始向前查找
// console.log(arr.lastIndexOf("orange",5));//4 从第5个索引开始向前查找


// indexOf() 返回一个指定的元素在数组中第一次出现的位置
console.log(arr.indexOf("orange"));//1  不指定起始索引,默认从0开始
console.log(arr.indexOf("orange",2));//4 从第2个索引开始向后查找
// lastIndexOf()  返回一个指定的元素在数组中最后出现的位置
console.log(arr.lastIndexOf("orange"));//6  不指定索引,默认从最后一个开始向前查找
console.log(arr.lastIndexOf("orange",5));//4 从第5个索引开始向前查找

1.3 数组遍历

forEach(function(currentValue, index, arr))方法 用于调用数组的每个元素,并将元素传递给回调函数

参数:必需,为一个回调函数,数组中每个元素需要调用的函数,函数参数如下:

  • currentValue 必需。当前数组中的元素
  • index 可选。当前元素的索引值
  • arr 可选。当前元素所属的数组对象

注意: 1. forEach() 对于空数组是不会执行回调函数的

  1. forEach用于替代for循环,但是并没有将for循环移除,只是将for循环放在了数组迭代器forEach方法的内部
  2. 回调函数内作用域是window
  3. 回调函数中的返回值对forEach方法的执行结果没有影响,forEach方法的返回值始终是undefined

代码示例
需求:遍历数组

// 创建一个数组
var arr = ["apple","orange","banana","pear","kiwi fruit","peach"];

// 1. 使用普通的for进行遍历
// console.group("使用普通的for进行遍历");
// for(var i = 0; i < arr.length; i++){
//     console.log("索引",i,"对应的数组元素为:",arr[i],"原数组为:",arr);
// }
// console.log("全局中打印i的值:",i);//全局中打印i的值: 6  全局中保存了i的值,i是全局变量
// console.groupEnd();

// // 2. 使用for...in循环进行遍历
// console.group("使用for...in循环进行遍历");
// for(var idx in arr){
//     console.log("索引",idx,"对应的数组元素为:",arr[idx],"原数组为:",arr);
//     // 注意打印结果:这里的index是字符串,利用的是 对象["属性"] 的方式获取数组中元素的值
// }
// console.log("全局中打印idx:",idx);//全局中打印idx: 5  全局中保存了idx的值,idx是全局变量
// console.groupEnd();

// // 3. 利用ES5新增方法进行遍历
// console.group("利用ES5新增方法进行遍历");
// arr.forEach(function(value,index,array){
//     console.log("索引",index,"对应的数组元素为:",value,"原数组为:",array);
// });
// //console.log("全局中打印index:",index);//报错 Error: index is not defined  说明index在forEach中是局部变量,避免全局变量的污染
// console.groupEnd();

1.4 映射数组

map(function(currentValue,index,arr)) 方法通过指定函数处理数组的每个元素,并返回处理后的数组

参数:同 forEach

返回值:一个新的数组,数组中的每一项都是每一次函数执行的结果组成的新成员
需求:将数组中的每一个成员首字母大写,并返回

// 创建一个数组
var arr = ["apple","orange","banana","pear","kiwi fruit","peach"];

console.log("原数组:",arr);//原数组: (6) ["apple", "orange", "banana", "pear", "kiwi fruit", "peach"]

// var mapArr = arr.map(function(value,index,array){
//     // 获取每一个成员字符串的第一个字符,并将其转为大写,拼接到原字符串中
//     var newVal = value.charAt(0).toUpperCase().concat(value.substring(1));
//     // 将转换后的新元素返回
//     return newVal;
// });

// console.log("进行处理后的数组为:",mapArr);//进行处理后的数组为: (6) ["Apple", "Orange", "Banana", "Pear", "Kiwi fruit", "Peach"]

var mapArr = arr.map(function(value,index,array){
    // 获取每一个成员字符串的第一个字符,并将其转为大写,拼接到原字符串中
    var newVal = value.charAt(0).toUpperCase().concat(value.substring(1));
    // 将转换后的新元素返回
    return newVal;
});

console.log("进行处理后的数组为:",mapArr);

1.5 填充数组

fill(value, start, end)方法 使用一个固定值来填充数组

参数:value 必需。填充的值 start 可选。开始填充位置 end 可选。停止填充位置(默认为 array.length)

注意:此方法会改变原数组

// 创建一个数组
// var arr = ["apple","orange","banana","pear","peach"];
// console.log("填充前原数组arr:",arr);
// // 使用固定值填充数组
// arr.fill("kiwi fruit");
// console.log("填充后原数组arr:",arr);//(5) ["kiwi fruit", "kiwi fruit", "kiwi fruit", "kiwi fruit", "kiwi fruit"] 默认填充每一个数组

// console.log("========= 分割线 =========");

// // 创建一个数组
// var arr2 = ["apple","orange","banana","pear","peach"];
// console.log("填充前原数组arr2:",arr2);//填充前原数组arr2: (5) ["apple", "orange", "banana", "pear", "peach"]
// // 指定索引之间的填充  左闭右开
// arr2.fill("kiwi fruit",2,4);
// console.log("填充后原数组arr2:",arr2);//填充后原数组arr2: (5) ["apple", "orange", "kiwi fruit", "kiwi fruit", "peach"]

// 创建一个数组
var arr3 = ["apple","orange","banana","pear","peach"];
console.log(arr3);
console.log("========= fill填充 =========")
// 指定索引之间的填充  左闭右开
arr3.fill("kiwi fruit",2,4);
console.log(arr3);

1.6 断言

  • some(function(currentValue,index,arr) 方法用于检测数组中的元素是否满足指定条件(函数提供)

    some() 方法会依次执行数组的每个元素:

    • 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测
    • 如果没有满足条件的元素,则返回false。
  • every(function(currentValue,index,arr) 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)

    every() 方法使用指定函数检测数组中的所有元素:

    • 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测
    • 如果所有元素都满足条件,则返回 true

some方法代码示例
需求:检测数组中是否有大于50的数字

// 定义一个数字
// var arr = [10,20,30,50,60,70,80,90];

// // 使用函数定义条件
// function checkNum(num){
//     return num >= 50;
// }

// // 使用some()检测
// var flag = arr.some(checkNum);
// console.log(flag);//true

every方法代码示例
需求:检测数组中的数字是否都大于50

// 定义一个数字
var arr = [10,20,30,50,60,70,80,90];
// 使用函数定义条件
function checkNum(num){
    return num >= 50;
}
// 使用every()检测
var flag = arr.every(checkNum);
console.log(flag);//false

需求:判断数组中的人名是否都是三个字

var pArr = ["张翠花","王二狗","李大壮","张狗蛋"];
var flag = pArr.every(function(value,index,arr){
    return value.length === 3;
})
console.log(flag);//true

// 兼容IE8及以下版本...
if(!Array.prototype.every){
    Array.prototype.every = function(){
        //...
    }
}

1.7 过滤

filter() 检测数值元素,并返回符合条件所有元素的数组

返回值 返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组

需求:检测数组中所有大于50的数字并返回

// 定义一个数字
var arr = [10,20,30,50,60,70,80,90];
// 使用函数定义条件
function checkNum(num){
    return num >= 50;
}
// 使用filter()检测
var resultArr = arr.filter(checkNum);
console.log(resultArr);//(5) [50, 60, 70, 80, 90]

1.8 累加器

  • reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值

  • reduceRight() 方法的功能和 reduce() 功能是一样的,不同的是 reduceRight() 从数组的末尾向前将数组中的数组项做累加

    参数:接收一个参数是函数,函数中有四个参数:当次累积的结果、当前成员值、当前索引值、原数组

    返回值:当次累积的结果,将会在下一次遍历的时候作为第一个参数传递

注:1. reduce是从前向后累加,reduceRight是从后向前累加。这两个方法会对所有的成员逐一处理并将结果返回。

// 创建一个数组
var arr = [10,20,30,40,50,60];

// 创建累加器需要的函数
// function sum(total,num){
//     return total + num;
//     // return total * num;
// }
// // reduce()累加器完成累加
// var result = arr.reduce(sum);

// 匿名方式
var result = arr.reduce(function(total,value,index,array){
    return total + value;
})
console.log(result);//累加结果:210

// reduceRight()  累乘等效果
function multiple(total,num){
    return total * num;
}
var result2 = arr.reduceRight(multiple);
console.log(result2);//累乘结果:720000000

1.9 bind方法

call()、apply() 与 bind()方法:这三个方法都是用于执行函数并改变函数的this指向

  • call 方法:接收多个参数, 第一个参数就是要改变的this指向,从第二个参数开始都是传递的参数
  • apply 方法:接收两个参数,第一个参数就是要改变的this指向,第二个参数是一个数组,数组中每一项才是传递的参数
  • bind 方法与call 方法类似,都是执行函数并改变函数的作用域
    • bind 方法接收多个参数: 第一个参数就是要改变的this指向,从第二个参数开始都是传递的参数
    • bind 方法与 call 之间的区别:call 改过 this 的指向后,会再执行函数,bind 改过 this 后,不执行函数,会返回一个绑定新 this 的函数
function sum(a,b){
    return a+b;
}

function reduce(a,b){
    return a-b;
}

var test = sum.apply(reduce,[10,20]);
console.log(test);//30

var test1 = sum.call(reduce,10,20);
console.log(test1);//30

var test2 = sum.bind(reduce,10,20);
console.log(test2);//ƒ sum(a,b){return a+b;}
console.log(test2());//30

你可能感兴趣的:(前端开发,JavaScript,javascript,es5,数组方法,bind)