前端总结系列

目录

这是《前端总结·基础篇·JS》系列的第二篇,主要总结一下JS数组的使用、技巧以及常用方法。


一、数组使用
1.1 声明数组
1.2 访问数组
1.3 类型检测
二、常用技巧
2.1 数组去重
2.2 数组深拷贝
2.3 字符串反序
三、方法列表
3.1 存取
3.2 字符串
3.3 修改
3.4 ES5
3.5 ES2015(ES6)
3.6 ES2016

一、数组使用

数组不是基本数据类型,但是非常常用,所以提前总结。

基本数据类型是String,Number,Boolean,null,undefined。

  • Boolean只有两个状态,true/false
  • null一般是开发者定义
  • undefined是JS引擎抛出的异常,通常在发现调用未声明的变量时抛出

1.1 声明数组

数组用中括号括起来,不同的值用逗号隔开。数组内的值有字符串需要用单引号或者双引号引起来。

var arr = []  // 声明一个空数组
var arr = [3,6,8,9] // 声明一个包含值3,6,8,9的数组
var arr = new Array(3,6,8,9) // 创建一个数组对象

1.2 访问数组

下标访问

数组的下标是从0开始的,最后一个值的下标是数组长度减去1。访问数组可以直接访问具体下标的一个值,也可以直接访问整个数组的值。


var arr = [1,2,3,4] console.log(arr) // 直接访问数组 | [1, 2, 3, 4]
console.log(arr[0]) // 通过下标访问 | 1
console.log(arr.length) // 访问数组的长度 | 4

遍历访问

如果需要逐个的访问数组中的值,你需要对数组进行遍历。可以用一般的for循环、for in或者ES6中的for of。


var arr = [1,2,3,4] // for
for(var x = 0; x < arr.length; x++){
console.log(arr[x]) // 通过下标访问
} // for in
for(x in arr){
console.log(arr[x]) // 通过下标访问
} // for of (ES6)
for(x of arr){
console.log(x) // 不需要通过下标访问
}

1.3 类型检测

检测一个对象有以下方法。更精确的检测数组请见请见jwalden


* typeof [] // object
* [] instanceof Array // false
* Array.isArray([]) // true | 通常用来检测数组
* Array.isArray(Array.prototype) // true | 这是一个例外情况

二、常用技巧

2.1 数组合并

可以用concat/push合并。concat返回合并后的新数组,push保存在原数组里。

  • 感谢园友 @loveyatou 提醒。在push方法中把apply写成了call,导致结果不符合预期。现已修正。 2017/03/17 13:45

  • PS:call和apply都是用来改变函数作用域的,用法基本一致,唯独传递参数的方法不一致。call是逐个输入,逗号隔开。apply是全部放在一个数组内。


var a = [1,2,3]
var b = [4,5,6] // concat 方法 var c = a.concat(b)
console.log(c) // [1, 2, 3, 4, 5, 6] // push 方法 Array.prototype.push.apply(a,b)
console.log(a) // [1, 2, 3, 4, 5, 6]

2.2 数组深拷贝

我们可以根据concat/slice方法返回新数组的特性来进行深拷贝,也可以直接用循环语句暴力深拷贝。

  • 把数组赋值给一个变量,只是复制了一个指向数组的指针(又叫引用)
  • 当我们改变原数组的值,新数组的值也跟着改变
  • 为了避免这样,你需要对数组进行深拷贝

// 深拷贝前 var arr = [1,2,3,4]
var newArr = arr // 把原数组赋值给新数组 arr.pop() // 删除原数组的一个值
console.log(arr) // 测试原数组的值 [1, 2, 3]
console.log(newArr) // 测试新数组的值 [1, 2, 3] // 深拷贝后 var arr = [1,2,3,4]
var newArrCopy = arr.concat() // 开始深拷贝,此处也可以使用arr.slice() arr.pop() // 删除原数组的一个值
console.log(arr) // 测试原数组的值 [1, 2, 3]
console.log(newArrCopy) // 测试新数组的值 [1, 2, 3, 4] // 暴力深拷贝 var arr = [1,2,3,4]
var newArr = [] // 为了使用数组的push方法,一定要定义数据类型为数组
for (var x = 0; x < arr.length; x++){
newArr.push(arr[x]) // 用循环逐个把值保存在新数组内
} arr.pop() // 删除原数组的一个值
console.log(arr) // 测试原数组的值 [1, 2, 3]
console.log(newArr) // 测试新数组的值 [1, 2, 3, 4]

2.3 数组去重

排序后去重,更多请见脚本之家


var newArr = arr.sort() // 排好序再比较
var newArrSaved = [newArr[0]] // 初始化为数组,用来存储最后的数据
for(var i =2;i<arr.length;i++){ // 从第二个开始
if(newArr[i]!==newArr[i-1]) // 判断当前值和上一个值是否一致
newArrSaved.push(newArr[i]) // 不一致则存在newArrSaved
}

2.4 字符串反序

首先将字符串序列化成数组,通过数组方法对数组反序,最后把数组转换成字符串。


'I See U.'.split('').reverse().join('') // ".U eeS I"

三、方法列表

ES5和ES6部分就当作参考手册吧,有时间再琢磨一下应用场景。

以下实例在此基础上进行


arr = [1,2,3,4]

3.1 存取

push在尾部添加,pop从尾部删除。

尾存取


push(element1, ..., elementN)
* arr.push(8) // [1, 2, 3, 4, 5]
pop()
* arr.pop() // [1, 2, 3, 4]

首存取

unshift在首部添加,shift从首部删除。


unshift(element1, ..., elementN)
* arr.unshift(5) // [5, 1, 2, 3, 4] shift
* arr.shift() // [1, 2, 3, 4]

3.2 转换

字符串

join默认以逗号分隔连接的字符串,传入参数可以进行自定义分割方式。


toString()
* arr.toString() // "1,2,3,4"
toLocalString()
* arr.toLocalString() // 和上面的效果一致,此方法仅在特殊语言中需要
join(separator)
* arr.join() // "1,2,3,4"
* arr.join('') // "1234"
* arr.join('-') // "1-2-3-4"

3.3 修改

排序

reverse把数组颠倒,sort对数组排序。sort默认按照unicode排序,传入function(a,b)可以自定义排序。更多请见MDN(内有对象按属性值排序的方法)


reverse()
* arr.reverse() // [4, 3, 2, 1]
sort()
* arr.sort() // [1, 2, 3, 4] 这个已经排好了序,所以不变

连接

concat连接数组,并返回一个新的数组。


concat(value1[, value2[, ...[, valueN]]])
arr.concat(9) // [1, 2, 3, 4, 9]

切割

切割比上面的稍微复杂点

  • slice为提取元素,splice为删除指定范围元素并添加新元素。slice的第二个参数,是结束的位置标记,不会包括在返回值内。

  • slice的返回值是提取元素组成的新数组。splice的返回值是删除元素组成的新数组,原始元素被修改。

  • slice在IE<9下使用时,会出现一些问题,需要使用腻子脚本。详见MDN


slice(begin,end)
* arr.slice(1,3) // [2, 3]
splice(start, deleteCount, item1, item2, ...)
* arr.splice(1,3,5) // [2, 3, 4] 返回值
* console.log(arr) // [1, 5] 原始元素被修改

3.4 ES5

需要精确检测数组请见jwalden


数组检查 Array.isArray(obj) // 检查是否为数组,返回值为true/false,兼容IE9+
* Array.isArray([1,2,3]) // true
* Array.isArray('123') // false
* Array.isArray(Array.prototype) // true
arr.every(callback[, thisArg])
* function isNotZero(element, index, array){return element!==0}
* arr.every(isNotZero) // true
arr.map(callback[, thisArg]) // 每个值都调用一次函数并且返回新数组
* function twice(element, index, array){return element*element}
* arr.map(twice) // [1, 4, 9, 16]
arr.reduce(callback,[initialValue]) // 将多维数组转为一维数组
arr.some(callback[, thisArg]) // 测试元素是否通过指定测试
arr.indexOf(searchElement[, fromIndex = 0]) // 返回满足条件的第一个索引,不存在返回-1
* arr.indexOf(3) // 2
arr.lastIndexOf(searchElement[, fromIndex = arr.length - 1]) // 由后向前查找
arr.forEach(callback[, thisArg]) // 对数组每个元素执行一次函数

3.5 ES2015(ES6)


Array.of(element0[, element1[, ...[, elementN]]]) // 创建新数组
* Array.of(3) // [3]
* Array(3) // [undefined × 3]
* Array.of([1,2,3]) // [Array[3]]
* Array([1,2,3]) // [Array[3]] Array.from(arrayLike[, mapFn[, thisArg]]) // 从类数组对象或可遍历对象中创建数组
* Array.from('berg') // ["b", "e", "r", "g"] arr.copyWithin(target, start, end) // 选定数组值,在一定范围内全部粘贴选定值
* arr.copyWithin(1,2,3) // [1, 3, 3, 4] arr.entries() // 返回新的数组迭代器(一定得复制给变量再迭代)
* var newArr = arr.entries()
* newArr.next().value // [0, 1]
* newArr.next().value // [1, 2]
* newArr.next().value // [2, 3]
* newArr.next().value // [3, 4] arr.keys() // 返回新的数组迭代器 arr.fill(value, start, end) // 用指定值填充一定范围数组
* arr.fill(0,1,3) // [1, 0, 0, 4] arr.filter(callback[, thisArg]) // 将满足条件的元素返回成新数组
* function isNotZero(element){return element!==0}
* arr.filter(isNotZero) // [1, 2, 3, 4] arr.find(callback[, thisArg]) // 返回满足条件的第一个值,不存在返回undefined
* function isNotZero(element){return element!==0}
* arr.find(isNotZero) // 1 arr.findIndex(callback[, thisArg]) // 返回满足条件的第一个元素的索引
* function isNotZero(element){return element!==0}
* arr.findIndex(isNotZero) // 0

3.6 ES2016


arr.includes(searchElement, fromIndex) // 判断数组是否包含指定值,返回true/false
arr.includes(2) // true

总结

  • 上一周一直在忙活Note这个小项目,现在已经上线了。以后会逐步增大项目复杂度。并且尝试用Vue和RN来分别对项目进行重构,后端则逐步接入Node.js和mongoDB。兼容性支持IE9及以上,根据IE7/8访客基数决定是否兼容。
  • 接下来的时间就安心的总结JS和更博客吧。关于Note开发过程中遇到的问题,以及解决方案,等整理好了再发出来。

文章主要参考的站点

ES5

前端兼容性方案

前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)的更多相关文章

  1. 前端总结·基础篇·JS(一)五大数据类型之字符串(String)

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(二)补充 前端总结·基础篇·JS(一)五大数据类型之字符串(String) 目录 这是& ...

  2. 前端总结·基础篇·JS(三)arguments、callee、call、apply、bind及函数封装和构造函数

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  3. 前端总结·基础篇·JS(四)异步请求及跨域方案

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  4. 前端总结·基础篇·JS(一)原型、原型链、构造函数和字符串(String)

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  5. 前端总结·基础篇·CSS(二)视觉

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·CSS(四)兼容 目录 一.动画(animation)(IE ...

  6. 前端总结·基础篇·CSS(一)布局

    目录 这是<前端总结·基础篇·CSS>系列的第一篇,主要总结一下布局的基础知识. 一.显示(display) 1.1 盒模型(box-model) 1.2 行内元素(inline) &am ...

  7. 前端总结·基础篇·CSS(三)补充

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 目录 一.移动端 1.1 视口(viewport) 1.2 媒体查询(medi ...

  8. 前端总结·基础篇·CSS

    前端总结·基础篇·CSS 1 常用重置+重置插件(Normalize.css,IE8+) * {box-sizing:border-box;}  /* IE8+ */body {margin:0;}  ...

  9. 小猪猪逆袭成博士之C++基础篇(二) 常量、处理类型、自定义头文件

    小猪猪逆袭成博士之C++基础篇(二) const .auto. decltype 上一章我们介绍了一些常用的类型和常见的问题,下面再介绍一些学习的时候不是特别常用但是在实际工程中很有用的一些东西. 一 ...

随机推荐

  1. 如何在windows xp下实现声音内录

    问题描述: 用屏幕录制软件录制一个视频,能够成功录制视频,但无法录制视频里面的声音. 问题原因: 因为现在的多数声卡,均无法直接通过声卡自身的功能实现内录和立体声混音. 这是由于声卡芯片厂商迫于RIA ...

  2. Bootstrap入门(四)表格

    Bootstrap入门(四)表格 <table>标签 首先,引入bootstrap的css文件,然后表格内容放在一个class为table的<table>标签中(class=& ...

  3. 游戏开发之在UE4中编写C++代码控制角色

    当你运行我们上次做完的项目,你可能会意识到我们移动的摄像机还是默认的那个摄像机,这个默认的摄像机可以自由飞翔.这一节,我们要使得开始的角色是我们的一个Avatar类的实例对象,并且使用键盘控制我们的角 ...

  4. 编写JQuery插件-1

    看到这篇文章的人相信大家都学会了jq,或者正在用jq,在这里简单介绍一下jq的插件封装: jQuery的插件主要分为3种类型: 1.封装对象方法的插件 这种插件是将对象的方法封装起来,用于对通过选择器 ...

  5. Eclipse / Intellij Idea配置Git+Maven+Jetty开发环境

    作者:鹿丸不会多项式 出处:http://www.cnblogs.com/hechao123  转载请先与我联系. 最近公司给加配了Mac,本想着花一个小时的时间搭好开发环境,最后全部弄好却用了一上午 ...

  6. .Net下的分库分表帮助类——用分库的思想来分表

    简介     在大型项目中,我们会遇到分表分库的情景.      分库,将不同模块对应的表拆分到对应的数据库下,其实伴随着公司内分布式系统的出现,这个过程也是自然而然就发生了,对应商品模块和用户模块, ...

  7. Spark源码分析之Spark Shell(上)

    终于开始看Spark源码了,先从最常用的spark-shell脚本开始吧.不要觉得一个启动脚本有什么东东,其实里面还是有很多知识点的.另外,从启动脚本入手,是寻找代码入口最简单的方法,很多开源框架,其 ...

  8. 自己用到的相关Linux命令,谨以记录

    1.查看磁盘使用情况 df -h(方便看些) df -l(字节大小,不方便看) 2.查看根目录下文件/文件夹大小 du -sh /*(/*表示根目录下所有文件) 3.查看文件列表时显示文件大小 ll ...

  9. E. Change-free

    Student Arseny likes to plan his life for n days ahead. He visits a canteen every day and he has alr ...

  10. [Linux] - Linux下安装jdk,tar方式

    下载jdk的linux下版本,下载页面http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.ht ...