JavaScript 数组数据类型
数组
-
就是一个存储数据的空间,里面会把你存储进去的所有数据
-
都按照顺序依次排好,每一个数据给一个编号(索引 / 下标)
-
编号从 0 开始
数组的创建方式
一、字面量创建数组
var arr = []
console.log(arr) // Array(0) 或 []
二、内置构造函数创建数组
var arr = new Array()
console.log(arr) // Array(0) 或 []
两种创建数组方法的使用
一、字面量
-
创建空数组:var arr = [ ]
-
创建一个带有数据的数组:var arr = [数据1, 数据2, 数据3, 数据4, …]
var arr = [100, 200, true, 'hello world', function () {}]
console.log(arr) // [100, 200, true, "hello world", ƒ]
二、内置构造函数
-
创建空数组:var arr = new Array( )
-
创建一个包含多个内容的数组:var arr = new Array(数据1, 数据2, 数据3, …)
var arr = new Array(300, 400, false, '你好 世界')
console.log(arr) // [300, 400, false, "你好 世界"]
- 创建一个包含一个内容的数组:var arr = new Array(数据1但不能是数字)
var arr = new Array('nihao')
console.log(arr) // ["nihao"]
- 创建一个指定长度、没有内容的数组:var arr = new Array(数字表示长度)
var arr2 = new Array(20)
console.log(arr2) // [empty × 20]
-
总结:
- 当你使用内置构造函数方法创建数组的时候
- 如果不传递参数,那么就是空数组
- 是一个数字的话,那么就表示数组的长度
- 不是一个数字的话,那么表示数组里面的一个数据
- 如果传递多个参数:
- 每一个参数都便是数组里面的一个数据
判断数组的方式
var a = []
console.log(Array.isArray(a)) // true 表示a是一个数组
var b
console.log(Array.isArray(b)) // false 表示b不是一个数组
数组的索引
-
索引:就是数组里面每一个数据的“编号”,从0开始递增,是一个读写的属性
-
读:获取第n位的数据是什么
- 如果数组有第n位,那么就是第n位的数据
- 如果数组没有第n位,那么就是undefined
-
写:写出数组第n位是什么数据
- 如果数组有第n位,那么就是把第n位的数据修改一下
- 如果没有第n位,那么就是加第n位
// 索引的 读写
var arr = ['hello', 'world', '你好', '世界']
console.log(arr[0]) // 获取数组中索引为 0 的数据 hello
console.log(arr[100]) // 获取数组中索引为 0 的数据 undefined
arr[1] = '后来换的' // 把 arr 数组的索引 1 位置数据写成 '后来换的'
arr[100] = '新来的' // 把 arr 数组的索引 100 位置数据写成 '新来的'
console.log(arr) // ['hello', '后来换的', '你好', '世界', ..., '新来的']
数组的length
-
表示数组的长度,也就是数组里面有多少个数据,是一个动态的属性,可以读,也可以设置(写)
-
读:获取到数组的长度
-
写:设置数组的长度
- 如果设置的长度比原先还小,那么后面的就算是删除了
- 如果设置的长度比原先还大,那么多出来的就都是空(empty)
// length 的读写
var arr = ['hello', 'world', '你好', '世界']
console.log(arr.length) // 读数组的长度 4
arr.length = 2 // 把数组的 length 改变成 2
console.log(arr) // ["hello", "world"]
arr.length = 100 // 把数组的 length 改变成 100
console.log(arr) // (100) ["hello", "world", empty × 98]
访问数组和对象的方法
一、通过索引挨个打印
var arr = ['hello', 'world', '你好', '世界']
console.log(arr[0]) // hello
console.log(arr[1]) // world
console.log(arr[2]) // 你好
console.log(arr[3]) // 世界
一、遍历数组
var arr = ['hello', 'world', '你好', '世界']
// 遍历数组
// 我需要的索引 0 1 2 3
// 数组的 length === 4
for (var i = 0; i < arr.length; i++) {
// i 得到的就是 0 1 2 3
console.log(arr[i])
// 当 i === 0 的时候, 就是 arr[0]
// 当 i === 1 的时候, 就是 arr[1]
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
// for ... in 循环遍历数组
// 表示我要遍历的是arr这个数组
for (var i in arr) {
// 利用这个 i 来遍历数组中的每一个成员
// arr['你要查询的名字']
console.log(i + ' 成员的值是 : ' + arr[i])
// 在这个循环里面
// 第一次的时候 i 就是 0
// 第二次的时候 i 就是 1
// 第三次的时候 i 就是 2
// 第四次的时候 i 就是 3
// 第五次的时候 i 就是 4 ...
}
var arr = [3,1,4,6]
for(var i in arr){
console.log(arr[i])
// 在这个循环里面
// 第一次的时候 i 就是 0,当 i == 0 时,arr[0] == 3
// 第二次的时候 i 就是 1,当 i == 1 时,arr[0] == 1
// 第三次的时候 i 就是 2,当 i == 2 时,arr[0] == 4
// 第四次的时候 i 就是 3,当 i == 3 时,arr[0] == 6
}
var arr = [3,1,4,6]
// for...of 中的value指的值
for(var value of arr){
console.log(value)
// 在这个循环里面
// 第一次的时候 value 就是 3
// 第二次的时候 value 就是 1
// 第三次的时候 value 就是 4
// 第四次的时候 value 就是 6
}
数组的操作方法
- 专门用来操作数组的方法
一、push( ) 方法
-
作用:向数组的后面追加数据
-
语法:数组.push(你要追加的数据1, 你要追加的数据2, …)
-
返回值:追加完毕以后,数组的长度
var arr = ['hello', 'world', '你好', '世界']
var res = arr.push(100, 200, true)
console.log('返回值是 : ' + res) // 返回值是:7
console.log(arr) // ["hello", "world", "你好", "世界", 100, 200, true]
二、pop( ) 方法
-
作用:删除数组的最后一个数据
-
语法:数组pop( )
-
返回值:被删除的那个数据
var arr = ['hello', 'world', '你好', '世界']
var res = arr.pop()
console.log('返回值是 : ' + res) // 返回值是 : 世界
console.log(arr) // ["hello", "world", "你好"]
三、unshift( ) 方法
-
作用:向数组最前面添加数据
-
语法:数组.unshift(你要添加的数据1, 你要添加的数据2, …)
-
返回值:添加完毕以后,数组的长度
var arr = ['hello', 'world', '你好', '世界']
var res = arr.unshift(100, 200, false)
console.log('返回值是 : ' + res) // 返回值是 : 7
console.log(arr) // [100, 200, false, "hello", "world", "你好", "世界"]
四、shift( ) 方法
-
作用:删除数组的最前面一个数据
-
语法:数字.shift( )
-
返回值:被删除的那个数据
var arr = ['hello', 'world', '你好', '世界']
var res = arr.shift()
console.log('返回值是 : ' + res) // 返回值是 : hello
console.log(arr) // ["world", "你好", "世界"]
五、reverse( ) 方法
-
作用:是反转数组
-
语法:数组.reverse( )
-
返回值:反转后的数组
var arr = ['hello', 'world', '你好', '世界']
var res = arr.reverse()
console.log('返回值是 : ' , res) // 返回值是:["世界", "你好", "world", "hello"]
console.log(arr) // ["世界", "你好", "world", "hello"]
六、sort( ) 方法
-
作用:给数组进行排序
-
语法:
- 语法1:数组.sort( ) --> 按照一位一位来进行升序排序
- 语法2:
- 数组.sort(function (a, b) { return a - b }) --> 数值从小到大排序
- 数组.sort(function (a, b) { return b - a }) --> 数值从大到小排序
-
返回值:排序好的数组
var arr = [1, 5, 2, 8, 11, 22, 13, 54, 32, 7, 6, 21, 9]
var res = arr.sort()
console.log(res) // [1, 11, 13, 2, 21, 22, 32, 5, 54, 6, 7, 8, 9]
console.log(arr) // [1, 11, 13, 2, 21, 22, 32, 5, 54, 6, 7, 8, 9]
var arr = [1, 5, 2, 8, 11, 22, 13, 54, 32, 7, 6, 21, 9]
var res = arr.sort(function (a, b) { return a - b })
console.log(res) // [1, 2, 5, 6, 7, 8, 9, 11, 13, 21, 22, 32, 54]
console.log(arr) // [1, 2, 5, 6, 7, 8, 9, 11, 13, 21, 22, 32, 54]
var arr = [1, 5, 2, 8, 11, 22, 13, 54, 32, 7, 6, 21, 9]
var res = arr.sort(function (a, b) { return b - a })
console.log(res) // [54, 32, 22, 21, 13, 11, 9, 8, 7, 6, 5, 2, 1]
console.log(arr) // [54, 32, 22, 21, 13, 11, 9, 8, 7, 6, 5, 2, 1]
七、splice( ) 方法
-
作用:
- 作用1:截取数组
- 作用2:截取数组以后,在截取位置替换新的内容
-
语法:
-
返回值:被截取出来的内容(返回值一定是一个数组)
- 不管你截取多少个数据,返回的数组里面就有多少个被截取出来的数据
- 如果你一个都不删除,返回的就是一个空数组
var arr = ['hello', 'world', '你好', '世界']
var res = arr.splice(2, 0)
console.log(res) // []
console.log(arr) // ["hello", "world", "你好", "世界"]
var arr = ['hello', 'world', '你好', '世界']
var res = arr.splice(1, 1, '新来的', '新来的2', '新来的3')
console.log(res) // ["world"]
console.log(arr) // ["hello", "新来的", "新来的2", "新来的3", "你好", "世界"]
var arr = ['hello', 'world', '你好', '世界']
var res = arr.splice(1, 2, '新来的', '新来的2', '新来的3')
console.log(res) // ["world", "你好"]
console.log(arr) // ["hello", "新来的", "新来的2", "新来的3", "世界"]
var arr = ['hello', 'world', '你好', '世界']
var res = arr.splice(1, 0, '新来的', '新来的2', '新来的3')
console.log(res) // []
console.log(arr) // ["hello", "新来的", "新来的2", "新来的3", "world", "你好", "世界"]
八、slice( ) 方法
-
作用:在不改变(影响)原始数组的基础上,从数组里面提取出来一段内容
-
语法:
- 语法1:数组.slice(从哪一个索引开始, 到哪一个索引结束) - 包前不包后
- 语法2:数组.slice(从哪一个索引开始, 负整数) - 包前不包后
- 注:负整数 等价于 (数组的length + 负整数)
- 语法3:数组.slice(从哪一个索引开始)
- 注:表示从哪个索引开始,提取出后面所有的内容
-
返回值:你提取出来的数据(一定是一个数组)
- 如果你有提取数据, 那么数组里面就是你提取的数据
- 如果你没有提取数据, 那么数组里面就是空数组
var arr = ['hello', 'world', '你好', '世界']
var res = arr.slice(1, 3) // 表示从索引1开始, 到索引3结束(不包含索引3)
console.log(res) // ["world", "你好"]
console.log(arr) // ["hello", "world", "你好", "世界"]
var arr = ['hello', 'world', '你好', '世界']
var res = arr.slice(1, -1) // 表示从索引 1 开始, 到索引 3 结束(不包含索引3)
// 写的是 -1 等价于 4 + -1 === 3
// 和你写 arr.slice(1, 3) 是一摸一样的
console.log(res) // ["world", "你好"]
console.log(arr) // ["hello", "world", "你好", "世界"]
var arr = ['hello', 'world', '你好', '世界']
var res = arr.slice(1) // 表示从索引 1 开始, 到最后结束(包含最后一个)
console.log(res) // ["world", "你好", "世界"]
console.log(arr) // ["hello", "world", "你好", "世界"]
九、concat( ) 方法
-
作用:就是把多个数组连接在一起,变成一个新的数组,不影响原始数组
-
语法:数组.concat(你要连接的数据或者数组1, 你要连接的数据或者数组2, …)
-
返回值:把所有的参数都连接到第一个数组身上,返回一个连接好的新数组
var arr = ['hello', 'world', '你好', '世界']
var res = arr.concat([1, 2, 3], [4, 5, 6], true, false, 100, 200)
console.log(res) // ["hello", "world", "你好", "世界", 1, 2, 3, 4, 5, 6, true, false, 100, 200]
console.log(arr) // ["hello", "world", "你好", "世界"]
十、join( ) 方法
-
作用:是把数组里面的每一个数据组合起来,变成一个字符串
-
语法:数组.join(‘你要连接每一个数据的连接内容’)
- 注:如果你不传递参数,默认使用**逗号(,)**进行连接
-
返回值:一定是一个字符串
var arr = [1,2,3,4,5,6]
var res = arr.join(' + ')
console.log(res) // 1 + 2 + 3 + 4 + 5 + 6
console.log(arr) // [1, 2, 3, 4, 5, 6]
var arr = ['h', 'e', 'l', 'l', 'o']
var res = arr.join('+')
console.log(res) // h+e+l+l+o
console.log(arr) // ["h", "e", "l", "l", "o"]
多维数组
一、二维数组
var userInfo = [
['李建', 20, '男','女'],
['李月', 18, '女', '睡觉'],
['李建2', 30, '男','运动'],
['李月2', 28, '女', '游戏']
]
console.log(userInfo[0][3]) // 女
console.log(userInfo[2][1]) // 30
for (var i in userInfo) {
for (var j in userInfo[i]) {
console.log(userInfo[i][j])
}
}
二、二维数组创建表格
-
表格的行数由数组的长度(外面大数组的长度)决定
-
表格的列数由每一条数据的长度(里面小数组的长度)决定
三、二维数组创建表格的案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#t{
width: 80%;
border: 1px solid red;
}
th,td{
border: 1px solid red;
height: 30px;
text-align: center;
}
</style>
</head>
<body>
<table id="t" cellspacing="0" cellpadding="0">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>爱好</th>
<th>住址</th>
</tr>
</thead>
<tbody id="tb">
</tbody>
</table>
</body>
<script>
var userInfo = [
['张三', 28, '男', '看书', '北京'],
['李四', 18, '男', '游戏', '武汉'],
['王五', 38, '男', '睡觉', '四川'],
['Rose', 20, '女', '跳舞', '武汉'],
['Tom', 25, '男', '运动', '北京'],
['Jack', 40, '男', '养生', '四川']
]
tb.innerHTML = tab(userInfo)
// 函数功能:
function tab(arr) {
var res = ''
for (var i = 0; i < arr.length; i++) {
res += '<tr>'
res += '<td>' + (i + 1) + '</td>'
for (var j = 0; j < arr[0].length; j++) {
res += '<td>'
res += arr[i][j]
res += '</td>'
}
res += '</tr>'
}
return res
}
</script>
</html>
拓展
一、indexOf
- 查找数组中是否存在某项,存在返回索引,不存在返回 -1
/*
编写函数indexOf(arr, item)
判断并返回item这个元素首次出现的下标
如果不存在返回-1
*/
function indexOf(arr, item) {
// 把数组里面的值挨个儿比一遍
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item) {
return i
}
}
return -1
}
var arr = [1, 2, 3, 4, 5, 6, 7]
console.log(indexOf(arr, 3)) // 2
二、includes
- 是否包含某项,存在返回true,不存在返回false
function includes(arr, item) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] == item) {
return true
}
}
return false
}
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(includes(arr, 5)) // true
冒泡排序
-
就是大数下沉
-
冒泡排序 - 是我们若干排序算法中最基础的一种
-
一个一个的进行比较后变量相交换
一、冒泡排序思路
-
先循环一遍,让每一个数字和后一个数字进行比较
-
如果前一个比后一个大,那么两个数字交换位置,否则不动
-
循环完毕得到的结果,就是最大的数字放到了数组的最后一位
-
循环一次能把最大的数放在最后面
- 一模一样的代码重复执行第二遍的时候,就把倒数第二大的数放到倒数第二大的位置
- 一模一样的代码重复执行第三遍的时候,就把倒数第三大的数放到倒数第三大的位置
- 一模一样的代码重复执行第n遍的时候,就把倒数第n大的数放到倒数第n大的位置
二、冒泡排序口诀
三、冒泡排序案例
/*
前面的数据和后面的数据进行比较
*/
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var tmp = arr[j + 1]
arr[j + 1] = arr[j]
arr[j] = tmp
}
}
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
/*
前面的数据和后面的数据进行比较
*/
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
var tmp = arr[j + 1]
arr[j + 1] = arr[j]
arr[j] = tmp
}
}
}
console.log(arr) // [9, 8, 7, 6, 5, 4, 3, 2, 1]
/*
后面的数据和前面的数据进行比较
*/
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = arr.length - 1; j > i; j--) {
if (arr[j] < arr[j - 1]) {
var tmp = arr[j]
arr[j] = arr[j - 1]
arr[j - 1] = tmp
}
}
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
选择排序
-
选择排序也是排序基础算法的一种
-
一个和所有的分别进行比较,之后变量相交换
一、选择排序思路
-
假设索引 0 是最大的
-
循环一次数组,找到最大的那个数字的索引
-
让最大的数字的索引和我们假设的最大的索引交换位置
-
例:var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
- 假设索引 0 是最大的数字
- 遍历数组的时候,发现最大的数字索引为 7
- 那么我们就让索引为 0 和 7 位置的数字交换
- 循环第二次,不需要管索引为 0 的数字了
- 假设索引为 1 的数是最大的数字
- 遍历数组的时候,找到比索引为 1 的数还要大的数字
- 那么就让这个更大的数字和索引为 1 的数交换位置 …
/*
我们确定好了 重复的代码执行 8 遍
第 n 遍 假设索引 循环开始 和谁交换
1 0 1 0
2 1 2 1
3 2 3 2
4 3 4 3
5 4 5 4
6 5 6 5
7 6 7 6
8 7 8 7
j j - 1 j j - 1
*/
二、选择排序案例
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
// 循环表示我要把我交换的那段代码重复执行多少遍
for (var j = 1; j < arr.length; j++) {
// j 分别得到的就是 1 2 3 4 5 6 7 8
// j 是几就表示第几遍
// 1. 假设最大的数字的索引
var maxIndex = j - 1
// 2. 循环遍历数组
for (var i = j; i < arr.length; i++) {
// 判断后面的数字是不是比我假设的这一位索引的数字大
if (arr[i] > arr[maxIndex]) {
// 让maxIndex = 这个比较大的数字的索引
maxIndex = i
}
}
// 3. 交换变量
// 让数组里面 maxIndex 位置的数字和数组里面 j - 1 位置的数字进行交换
var tmp = arr[j - 1]
arr[j - 1] = arr[maxIndex]
arr[maxIndex] = tmp
}
console.log(arr) // [9, 8, 7, 6, 5, 4, 3, 2, 1]
选择排序案例2
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 1; i < arr.length; i++) {
var minIndex = i - 1
for (var j = i; j < arr.length; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j
}
}
var tmp = arr[minIndex]
arr[minIndex] = arr[i - 1]
arr[i - 1] = tmp
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[j] > arr[i]) {
var tmp = arr[i]
arr[i] = arr[j]
arr[j] = tmp
}
}
}
console.log(arr) // [9, 8, 7, 6, 5, 4, 3, 2, 1]
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[i]) {
var tmp = arr[i]
arr[i] = arr[j]
arr[j] = tmp
}
}
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
var arr = [5, 3, 7, 2, 1, 4, 6, 9, 8]
for (var j = 0; j <arr.length; j++) {
// 假设最小的数字的索引是j
var min = j
// 循环遍历数组
for (var i = j + 1; i < arr.length; i++) {
// 判断后面的数字是不是比我假设的这一位索引的数字小
if (arr[min] > arr[i]) {
// min = 这个比较小的数字的索引
min = i
}
}
// 当i !=j 的时候,交换变量
if (min != j) {
var tmp = arr[j]
arr[j] = arr[min]
arr[min] = tmp
}
}
console.log(arr) // [1, 2, 3, 4, 5, 6, 7, 8, 9]
数组的深拷贝和浅拷贝
一、浅拷贝
- 就是地址拷贝(简单的赋值)
arr = arr2 // 将会共享一个地址
二、深拷贝
-
实际是复制内容
-
全局变量和里面的局部变量互相独立
三、拓展:数据的值传递和引用传递
-
基本数据类型属于值传递,本质就是一个简单的复制
-
引用数据类型属于引用传递,本质就是共享地址