1. 数组
数组 Array :是一种可以按顺序保存数据的数据类型
1.1 声明数组
let 数组名 = [ 数据1, 数据2, 数据3, ..., 数据n ]
或
let 数组名 = new Array(数据1, 数据2, 数据3, ..., 数据n)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let day = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日',10]
</script>
</body>
</html>
- 数组是按照顺序保存,每个数据都有自己的编号,也叫索引(从0开始)
- 数组可以保存任意类型的数据
- 数组中保存的每个数据都叫一个数组元素
1.2 使用数组
数组名[下标]
想知道数组的长度,需要使用:数组名.length
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let day = ['星期一','星期二','星期三','星期四','星期五','星期六','星期日']
console.log(day[6]) //星期日
console.log(day.length) //7
</script>
</body>
</html>
1.3 操作数组
1.3.1 遍历数组
用循环把数组中每个元素都访问到,一般会用for循环遍历
1.3.2 数组的新增
一. 数组.push()
方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度 (重点)
语法: arr.push(元素1, 元素2, ...)
let arr = [10, '吕']
arr.push(22, '张')
console.log(arr) //[10, '吕', 22, '张']
二. arr.unshift(新增的内容)
方法将一个或多个元素添加到数组的开头,并返回该数组的新长度
语法: arr.unshift(元素1, 元素2, ...)
let arr = [10, '吕']
arr.unshift(22, '张')
console.log(arr) //[22, '张', 10, '吕']
1.3.3 数组的删除
一. 数组.pop()
方法从数组中删除最后一个元素,并返回该元素的值
语法: arr.pop()
let arr = [10, '吕']
arr.pop()
console.log(arr) //[10]
二. 数组.shift()
方法从数组中删除第一个元素,并返回该元素的值
语法: arr.shift()
let arr = [10, '吕']
arr.shift()
console.log(arr) //['吕']
三. 数组.splice()
方法删除指定元素(!!!)
语法: arr.splice(起始位置, 删除几个元素)
- 起始位置指定修改的开始位置(从0计数)
- 第二个参数表示要移除的数组元素个数
- 如果只有一个参数,则默认从指定的起始位置删除到最后
let arr = [10, '吕', 22]
arr.splice(1, 1)
console.log(arr) //[10, 22]
1.3.4 数组的排序
语法: 数组.sort()
1.4 冒泡排序
- 冒泡排序是一种简单的排序算法。
- 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
- 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冒泡排序</title>
</head>
<body>
<script>
let arr = [1,2,3,4,5]
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] < arr[j+1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.log(arr);
</script>
</body>
</html>
2. 函数
函数function: 被设计为执行特定任务的代码块。
为什么需要函数?
- 函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用(eg: promp()、alert()、console.log()...)
2.1 函数的声明
function 函数名(形参列表){
函数体
return //如果需要返回值,则加 return
}
函数名的命名规范:
- 和变量命名基本一致
- 尽量使用小驼峰命名法
- 前缀用动词
2.2 函数的使用
//函数调用,这些函数体内的代码逻辑会被执行
函数名(实参列表)
//对于返回值函数,可以用一个变量去接收
let v = 有返回值的函数()
注意: 函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。
传参和返回值:
- 开发中尽量保持实参和形参数量一致
- 如果形参过多 会自动填上undefined
- 如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
- return行后面的代码不会再执行
- 不对函数进行返回(不写return),则默认返回 undefined
2.3 作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
全局作用域: 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
局部作用域: 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。
特殊情况: 如果在函数内部,变量没有声明直接赋值,会默认当全局变量看,但是不建议这种写法。
变量的访问原则:(就近原则)
- 只要是代码,就至少有一个作用域
- 写在函数内部的访问局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 在能够访问到的情况下先局部, 局部没有在找全局
2.4 匿名函数
具名函数: function fn () {}
匿名函数: function () {}
匿名函数就是没有名字的函数,无法调用,无法直接使用
两种使用方式:
- 函数表达式
- 立即执行函数
2.4.1 函数表达式
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式。
语法:
//声明
let fn = function(){
函数体
}
//调用
fn()
函数的形参和实参使用跟具名函数一致。
2.4.2 立即执行函数
为什么使用立即执行函数?
- 避免全局变量之间的污染
语法:
//方式1
(function (形参1, 形参2, ...) {
...
})(实参1, 实参2, ...);
//方式2
(function (形参1, 形参2, ...) {
...
}(实参1, 实参2, ...));
立即执行函数不需要调用,函数后面多余的()
就是为了调用函数用的,所以会立即执行。
注意: 多个立即执行函数时,后面要加;
。
3.逻辑中断
逻辑中断多用于给参数赋默认值,类似参数的默认值写法
function getSum(x, y){
x = x || 0 //如果没传实参,x会等于0
y = y || 0
console.log(x + y)
}
getSum(1, 2)
什么是短路?
- 只存在于
&&
和||
中,当满足一定条件会让右边代码不执行 - 通过左边能得到整个式子的结果,因此没必要再判断右边
- 无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值