下面是我对 ES3/ES5/ES6 一些数组操作的总结,附带了一些我曾经遇到和用上的一些实际需求。

map处有待更内容。

首先先来讲讲ES3的数组方法


(影响原数组)栈方法之 push:可向数组的末尾添加一个或多个元素,并返回新的长度。

好像没有什么可说的?

var a = [1];
a.push(2);
console.log(a); // [1,2]
console.log(a.push(8)); //3

(影响原数组)栈方法之 pop:用于弹出数组最后一个元素,返回该元素的值

push 和 pop 组成了后进先出的栈数据结构。

var a = [1,2,3];
console.log(a.pop()); // 3
console.log(a); // [1,2]

通过这个函数,可以帮我们实现一道OJ题目,输出文件的后缀名

const getExtName = (filename) => {
let position = filename.indexOf('.');
if (position !== 0 && position !== -1) {
filename = filename.split('.');
postfix = filename.pop();
return '.' + postfix
} else {
return ''
}
};
console.log(getExtName('xx.avi')); // .avi

(不影响原数组)join:接收一个参数作为分隔符,以字符串的形式返回。(这其实是两个功能,1. 将每个元素都转成字符串 2.用自定义的连接符分割)

它接受0参数或者1个参数,若是传了多个参数只有第一个是有效的。

  • 参数若是为无,默认为','
[考古时刻]

古代的前端代码或者古代的博客往往能看到这样的东西(哦,让我想起来了 Ext 的 tpl,也就是 JSX 语法的前前前代思想吧)

var array = ['1','2','3'];
var html="<h1>"+array.join("</h1><h1>")+"</h1>";

上述可以生成用array作为数据的指定结构的html.

通过 join,我们能够将[数组]变为[字符串],而我们若要倒着来,可以用 split

'a,b,c'.split(','); // ["a", "b", "c"]
'a,b,c'.split(',').join(',') // 'a,b,c'

(不影响原数组)slice[start, ?end]:用于切割并且创造一个新的数组

  • 1个参数(普通形态): 从开始位置截取到结尾
  • 2个参数(完全体): 从开始位置截取到结束位置 [a, b) 不包括结束位置本身 -.-
  • 结束位置还可以是负数( 实际计算为:该负数 + 数组长度)

    结束位置小于起始位置,返回 空数组 []

var a = [1, 2, 3];
console.log(a.slice(1)); // [2, 3]
console.log(a.slice(1, 2)); // [2]
console.log(a); // [1, 2, 3] - 原数组没有被改变
console.log(a.slice(1, -1)); // (-1 + 3) = 2 => a.slice(1, 2) => [2]
console.log(a.slice(1, -100)); // []

slice 有一个挺经典的的代码: [rgb颜色值转换为十六进制]

rgb值 (0, 0, 0) ~ (255, 255, 255),十六进制 #000000 ~ #ffffff

const rgbToHex = (color) => {
let rgb = color.split(','); // 将 rgb 字符串分解,例子:'rgb(1, 1, 1)',得到 ['rgb(1', '1,', '1)']
let r = parseInt(rgb[0].split('(')[1]), // 去掉数组第一项的多余的东西
g = parseInt(rgb[1]), // 第二项本身很干净
b = parseInt(rgb[2].split(')')[0]); // 同第一项注释
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
// 这里采用了位移操作 256 * 256 * 256 => 2^8 * 2^8 * 2^8
// 这里的 (1<<24) 是为了防止我们的最高位的 r 颜色数字小于 16 的情况,出现了五位数的情况,如 #10000,颜色值嘛,得是六位的
}
let color = 'rgb(10,128,233)';
console.log(rgbToHex(color));

(1<<24)是为了规避 rgb 最高的 r 转化的数字 < 16 的情况

通过slice(1),我们很容易地把多加上的那位1给去掉啦~是不是很取巧,我反正感觉这题、这需求挺经典的。


(影响原数组)splice(start, ?cutLen, ?data):用于截取数据,插入数据,删除数据。!!操作的是数据本身

这里郑重地提一句,字符串不能借用splice,即使使用了Array.porotpye.splice.call,因为在规范中,字符串是不可变的,使用splice会改变原数组。所以slice可以在字符串中用,而splice不能。所以,如果我们要在字符串中使用,需要注意。a.转换成数组 b.注意splice返回的是被替换的东西,而不是本身。

以上同理。pop、push、reverse等改变原数组的,在 string 上都不能通过 call 来借用哦。

参数有三:

  • 1.[开始位置]: 当只有1个参数的时候:从数组的开始位置删掉剩下的所有数据,返回删掉的数据。

    slice就像只是我们想象中的裁剪,而splice则是现实中的,从splice中醒来,已是物是人非。splice是直接对数组进行操作的。

    var array = [15, 5, 10, 2, 0];
    console.log(array.splice(1)); // [5, 10, 2, 0]
    console.log(array); // [15]
  • 2.[开始位置,截断的个数](注意,这和 slice 的第二个参数意义可是不一样的,这是 cutLen):以 start 为起点,cutLen 为长度,删掉 [start, start + cutLen) 的元素
    var array = [15, 5, 10, 2, 0];
    array.splice(1, 2);
    console.log(array); // [15, 2, 0]
  • 3.[开始位置,截断个数,插入的数据]: (start, cutLen, data): 以 start 为起点, cutLen 为长度,删掉 [start, start + cutLen] 的元素,并填充 data 到删除的位置
    var array = [15, 5, 10, 2, 0];
    array.splice(2, 2, 8);
    console.log(array); // [15, 5, 8, 0]

(影响原数组)队列方法shift:将数组第一个元素从其中删除,并且返回第一个元素的值

和pop差不多

var a = [1,2,3];
console.log(a.shift()); // 1
console.log(a); // [2,3]

(影响原数组)unshift: 在数组开头添加元素,返回该元素值

pop,unshift,shift,push 这几个都是直接对原数组进行操作的。

unshift和shift组成的数据结构也是栈,只是栈顶和栈尾位置交换了罢了。

var a = [1,2,3];
console.log(a.unshift(4)); // 4
console.log(a); // [4,1,2,3]

(不影响原数组)concat:用于连接两个或者多个数组,返回一个新的数组

concat是不会改变原来的数组的

var a = [1,4];
var b = [2,4];
var c = [];
console.log(c.concat(a,b)); // [1,4,2,4]
console.log(a,b); // [1,4] [2,4]

(影响原数组)数组颠倒之 reverse:用于将数组元素颠倒顺序

无参数,无视参数, !!!!!操作的是数组本身,会改变原数组

var a = [1,2,3,5];
console.log(a.reverse()); // [5,3,2,1]

(影响原数组)排序sort(fn):排序方法

参数:fn(a,b):比较函数,无参数的时候按照字母表 ASCII 升顺排序

var a = [1, 2, 3, 5, 10, 25];
console.log(a.sort()); // [1, 10, 2, 25, 3, 5]

看,我们发现了什么?这个排序结果明显不是我们所想要的结果,对吧哈哈?是不是很有趣!

这是因为 sort()默认对每一个 子项 调用转型方法 toString(),之后才进行判断。而这个时候其实是根据 ASCII 码的大小来判断的。因此 "15" < "5"。先比较第一位,再比较第二位。

即使每一项都是 Number ,如果我们不后期加工,sort()比较的也是每一项转化为的String的大小。

  • 那么就让我们来实现一下其内部的方法使得 sort 能够按照我们的预期工作吧!

    var a = [1, 2, 3, 5, 10, 25];
    a.sort((a, b) => a - b);
    console.log(a); // [1, 2, 3, 5, 10, 25]

    我已经总结出来了一个规律。正所谓后来居上

    • return a-b; 即是从小到大(a-b)排序(b是在后面的,所谓后来)
    • return b-a; 即是从大到小(b-a)排序
  • 百尺竿头,更进一步!让我们再来增加一下难度吧,实现对简单对象根据某个 key 值排序

    let obj_list = [{
    name: 'li',
    value: 99
    }, {
    name: 'chen',
    value: 100
    }, {
    name: 'huang',
    value: 1
    }]
    console.log(obj_list.sort((a, b) => { return a.value - b.value }))
    // 排序结果:'huang','li','chen'
  • 在一次面试(深圳-XMind)中,我还得知了这个函数还可以用于随机排序,其实就是利用了sort(compare)的特性。附:官方特性

    • 1.可选参数compare需为函数,sort函数使用compare函数比较数组中的两个元素,因此,compare函数需要两个参数compare(a,b)。
    • 2.当compare函数返回任何大于0的值时,它将使第1个参数的索引值小于第2个参数的索引值
    • 3.当compare函数返回任何小于0的值时,它将使第2个参数的索引值小于第1个参数的索引值

    所以!!!如果我们要乱序,我们只要让返回的随机数 大于0和小于0 的概率一样即可!上代码:

    var a = [1, 2, 3, 5, 10, 25];
    a.sort((a, b) => 0.5 - Math.random());
    console.log(a);


就这样,ES3常用的数组方法告一段落;下面就是随着时代的进步所衍生出的ES5,6的方法了

我们曾经所有的复杂的,麻烦的操作,在新技术中,都被简化,就像拖把和拖把一样,这就是进步,拥有进步能力的语言往往不容易被这个时代所淘汰。

  • ES5 更新了 indexOf 方法
  • ES5 增加了 every/filter/some/forEach/map 这些方法都不会修改数组的值

(不影响原数组)Array.prototype.indexOf(此方法在 ES3 也有,不过那是针对 String的):返回在该数组中第一个找到的元素位置,若不存在则返回 -1

我们可以首先来用ES3来模拟一下先,有助于我们理解。

Array.prototype.indexOf = function (index) {
var res = -1,
now = null,
len = this.length;
if (len == 0) return res;
for (var i = 0; i < len; i++) {
now = this[i];
if (index == now) {
res = i;
break;
}
}
return res;
}
var test = ['234', '23424', '30'];
console.log(test.indexOf('30'));

(不影响原数组)forEach:对数组中的每一项运行给定函数,这个方法没有返回值.

参数为function类型,默认有传参(遍历数组内容,对应数组索引,数组本身)

在这里引用一个segmentfault的回答:https://segmentfault.com/q/1010000006127658?_ea=1022444,以下为引用的内容

题目之添加一个 fullName

所传函数有三: forEach(function (子项,Index,所有项All) {})
  • 不用 forEach

    var users = [
    {
    lastName: 'Li',
    firstName: 'Lei'
    },
    {
    lastName: 'Han',
    firstName: 'Meimei'
    }
    ];
    // 在这里,我们用原始的语法处理
    for (var i = 0; i < users.length; i++) {
    users[i].fullName = users[i].firstName + users[i].lastName;
    }
    console.log(users);
    • 分析缺点:我们多了个 i 变量,直观上多了个 for 循环
    • 若是用forEach
  • 使用 forEach

    users.forEach(function(user,index,arr){
    user.fullName = user.firstName + user.lastName;
    });
    console.log(users);

你可能认为这里的 forEach 其实改变了数组的值,其实不然。

只需知道,引用对象是不同的,他们指向的是一个内存位置,而非实际的对象。

var arr = [1, 2, 3];
arr.forEach(item => {
item = 8;
});
console.log(arr); // [1, 2, 3]

(不影响原数组)map:对数组中的每一项运行给定函数,返回每次调用结果组成的数组。

我们能够在 Redux 中的 reducer 看到大量的 map 函数,因为 redux 追求这种函数式极简的酷炫的风格;

Vue 中的 v-for 本质上就是 map 实现的;

map是指映射,和英文中的地图不同。

所传函数有三: forEach(function (子项,Index,所有项All) {})
  • map(function (item, index, allItem) {})
var a = [1, 32, 442, 234];
b = a.map(item => item + 1);
console.log(a, b); // [1,32, 442, 234] [2, 33, 443, 235]
  • 如果我们什么都返回,则每一项都会返回 undefined
var a = [1, 32, 442, 234];
c = a.map(() => {});
console.log(c); // [ undefined, undefined, undefined, undefined ]
  • 回调函数中第二个参数 index 的作用,在react中我们主要将它赋值给key
d = a.map((item, i) => {
console.log(i); // 0,1,2,3
});
  • 回调函数中第三个参数,所有元素,即数组本身
e = a.map((item, i, array) => {
console.log(array); // 最后会打印四遍 [1,34,442,234]
})

(不影响原数组)filter:对数组中的每一项运行给定函数,返回该函数会返回 true 的项组成的数组

以上不改变原数组的函数如果结果需要多次使用,最好都定义一个新的变量来存储。

让我看一个简短的filter,是不是有一种四两拨千斤的感觉。

var a = [{
flag: false,
name: 'lihua'
}, {
flag: true,
name: 'zengcuo'
}];
console.log(a.filter(item => item.flag)); // [{flag:true,name:'zengcuo'}]

除此之外,ES5 新增了两个归并的方法

  • (不影响数组)reduce(function(pre, next, index, array) {}) 从左到右
  • (不影响数组)reduceRight(function(pre, next, index, array) {}) 从右到左
let arr = [1, 2, 3];
console.log(arr.reduce((pre, next) => pre + next)); // 6

(不影响原数组)some和every

  • some: 对数组中的每一项运行给定函数,如果函数对任一项返回 true,就会返回 true,否则 false
  • every:对数组中的每一项运行给定函数,如果函数对所有的项都返回 true,才返回 true,否则 false
var people = ['crimeA', 'crimeB'];
console.log(people.some(item => item.indexOf('crimeA') > -1)); // true 只要有罪行A 就返回 true
console.log(people.every(item => item.indexOf('crimeA')> -1)); // false 每个数组都要 罪行A 才返回 true

以上就是 ES5 的方法啦,让我们简介下 ES6 的方法吧!

  • Array.from:从一个类似数组或可迭代的对象中创建一个新的数组

可以用来作数组去重

let arr = [1, '11', '11', 1, 8,];
let res = Array.from(new Set(arr));
console.log(res); // [1, '11', 8]
  • Array.isArray(arr):返回传递的值是否是数组
  • Array.fill(target, start, end):用一个固定的值填充一个数组

可以用来快速的繁殖数组

let arr = new Array(3);
let obj = {a: 1};
arr.fill(obj);
console.log(arr); // [ { a: 1 }, { a: 1 }, { a: 1 } ]
  • Array.includes():判断是否包含某个值
  • Array.find(callback)
  • Array.findIndex
  • Array.keys()
  • Array.values()
  • Array.entries()

complete.

包括ES6在内的数组操作(待更)的更多相关文章

  1. es6 新的数组操作

    ES6数组新增的几个方法 2017年03月24日 13:38:04 tang15886395749 阅读数:10461 标签: ES6数组新增方法 更多 个人分类: js相关   关于数组中forEa ...

  2. ES6之数组操作

    es6中对于数组操作添加了4种方法: 1.map —— 映射(一个对应一个) 2.reduce —— 汇总(多个出来一个) 3.filter —— 过滤 4.forEach —— 迭代/循环. 1.m ...

  3. C语言数组操作和指针操作谁更高效

    在上一篇博文  代码优化小技巧(持续更新......) 第三条关于数组和指针谁更高效, 意犹未尽, 决定单独拉出一篇来讲 1. 数组和指针操作对比 #include <stdio.h> i ...

  4. js数组操作find查找特定值结合es6特性

    js数组操作find查找特定值结合es6特性

  5. ES6中的数组

    数组是js中很重要的数据类型,虽然在 ES5 中,关于数组的方法和属性很多.但为了更加简洁.高效的操作数组,ES6 中又在数组原型上和实例上新增了一些方法. 一.Array方法 1.1 Array.f ...

  6. Javascript数组操作

    使用JS也算有段时日,然对于数组的使用,总局限于很初级水平,且每每使用总要查下API,或者写个小Demo测试下才算放心,一来二去,浪费不少时间:思虑下,堪能如此继续之?当狠心深学下方是正道. 原文链接 ...

  7. JavaScript中数组操作常用方法

    JavaScript中数组操作常用方法 1.检测数组 1)检测对象是否为数组,使用instanceof 操作符 if(value instanceof Array) { //对数组执行某些操作 } 2 ...

  8. 【原】javascript数组操作

    继续我的第二遍<javascript高级程序设计第三版>,今天要做的笔记是array 一.数组的操作 1.数组的创建: var colors= new Array(); //创建一个数组 ...

  9. PHP数组操作大全

    <?php /** * File: phpstudy : array_test.php * Created by PhpStorm. * User: IhMfLy Pheonix@jtv-070 ...

随机推荐

  1. 【bzoj4296】再见Xor

    4269: 再见Xor Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 176  Solved: 107[Submit][Status][Discuss ...

  2. oracle级联更新与级联删除

    Oracle级联删除:可以使用外键约束来实现,建立表的主外键关系,给列设置级联删除.如下: ——创建了CLASS表,并设置ID字段为主键. -- Create tablecreate table CL ...

  3. Unity shader saturate

    当你想将颜色值规范到0~1之间时,你可能会想到使用saturate函数(saturate(x)的作用是如果x取值小于0,则返回值为0.如果x取值大于1,则返回值为1.若x在0到1之间,则直接返回x的值 ...

  4. linux内核被加载的过程

    二,linux内核被加载的过程 一,linux安装时遇到的概念解析 内核必须模块vmlinz(5M左右)不认识硬盘,原本是需要写跟loader中一样的内容,来加载非必要模块. 内核非必要的功能被编译为 ...

  5. Smarty3——变量修饰器

    变量修饰器可以用于变量, 自定义函数或者字符串. 使用修饰器,需要在变量的后面加上|(竖线)并且跟着修饰器名称. 修饰器可能还会有附加的参数以便达到效果. 参数会跟着修饰器名称,用:(冒号)分开. 同 ...

  6. Part5核心初始化_lesson3---关闭看门狗

    1.看门狗---作用 2.看门狗工作方式 3.原理图 时钟源来自于PCLK经过分频器,经过选择器,输出到作为看门狗定时器,WTDAT为一个预载值,当它计数为零的时候,还没有给WTDAT赋值,那么它会发 ...

  7. SpringMVC——拦截器

    Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,自定义的拦截器必须实现HandlerInterceptor接口 preHandle():这个方法在业务处理 ...

  8. 使用Monkey对APP进行随机测试

    Monkey测试简介 Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕.滑动Trackball.按键等操作来对设备上的程序进行压力测试,检测程序多久的时间 ...

  9. Java IO输入输出流File 字节流

    public static void main(String[] args) throws IOException { //创建源 File f =new File("file/stream ...

  10. ColorMatrixFilter色彩矩阵滤镜;

    包 flash.filters 类 public final class ColorMatrixFilter 继承 ColorMatrixFilter  BitmapFilter  Object 使用 ...