回顾
数据类型
简单:string、number、boolean、null、undefined
复杂:function、object、array
数据类型的判断
typeof
两种语法
- typeof 数据
- typeof(数据)
区别:
- 如果要判断的数据是需要运算的,则要使用带括号的语法
- 否则typeof只会判断离他更近的那个数据的类型
结果
- “abc” :string
- 123 :number
- true :boolean
- null :object
- undefined :undefined
- function :function
- object :object
- arr :object
数据类型的转换
转String
- String()
- toString()
转number
- Number()
- parseInt
- parseFloat
- 运算符的隐式转换
转布尔
- Boolran()
- 取反逻辑符 !
运算符
算术运算符
+
-
*
/
%
+=、-=、/=、%=、*=
比较运算符
==
===
>=
<=
>
<
!=
!==
逻辑运算符
- &&
- ||
- !
自增、自减运算符
- 前置++、后置++
- 前置–、后置–
- 前置:操作数先运算+1/-1,之后在去与其他操作数进行运算
- 后置:先于其他操作数运算,之后操作数在+1/-1
验证数字的方法
- isNaN()
- 返回值:一个布尔值,用于表示当前这个值是否为一个合法数字
- 为true表示不是一个合法数字
- false:表示是一个合法数字
- 返回值:一个布尔值,用于表示当前这个值是否为一个合法数字
// let a = 10;
// let b = 20;
// b = a + b;
// b += a
流程控制
分支语句
-
if(条件){jscode。。。}
- 当条件满足时,执行后面花括号中的代码,如果不满足不做任何操作
-
if。。。else
- 当条件满足时,执行后面花括号中的代码,如果不满足,则执行else花括号后的代码
-
if。。。else if
-
写入多个条件,当我的代码进入时,如果满足条件1,则执行后面花括号中的代码,如果不满足,则继续往后判断条件2,如果满足就执行代码,不满足则不做任何操作
-
注意:即使两个条件同时满足,也只会执行第一个条件后面的代码。
-
-
if。。else if。。else
- 上述语法的结合体,当前面书写的条件都不满足时,则执行else后的代码。
-
switch case
switch(要判断的变量){
case 情况1 :
满足条件 执行的代码
break; 如果不加break,代码会穿透
case 情况2 :
满足条件 执行的代码
break; 如果不加break,代码会穿透
case 情况3 :
满足条件 执行的代码
break; 如果不加break,代码会穿透
default:
所有情况都不满足时,执行的兜底代码。
}
- 注意:在switch语句中,不能进行范围的判断
- 要判断的变量,必须和case后的情况 === 为true,才叫满足条件
- 不能使用逻辑运算符
- 穿透:下一个case不管成立与否,都会执行,直到switch结果或遇到break;
- 穿透会从第一个满足条件的case开始向下穿透。
循环语句
循环三要素
- 什么时候开始
- 什么时候结束
- 步长
- while
- 语法:while(条件){循环的代码/循环体}
- 开始:一般以某个变量或结果值作为开始
- 结束:当我判断的某个变量达成某个条件时,
- 步长:对变量的操作,然后与条件中的某些值产生联系
- dowhile
- 与while的区别在于,dowhile不管条件成立与否,都会先执行一次,在判断条件
- 语法:do{循环体}while(条件)
- for
- 语法:for(定义初始变量;条件;步长){循环体}
- 注意:循环是条件、步长、代码三者在循环
- 循环控制语句
- break:退出当前循环
- continue:跳过当前这次循环,继续下一次循环
- while
for (let i = 1; i < 5; i++) {
// setTimeout(function(){
// console.log(i);
// },1000)
console.log(new Date().getTime());
debugger;
}
for (var i = 1; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
函数
-
是js内一种代码的集合
-
看作一个“盒子”,盒子里面装载了我们需要执行的代码,之后在我需要的时候就可以把这个函数中的函数倒出来执行。
-
函数的两个阶段
- 定义阶段
- 声明式
- function 函数名(形参){jsCode}
- 表示式
- let 变量名 = function(形参){jsCode}
- 调用阶段
- 函数名(实参)
- 形参:形式参数,并没有具体的值,且他的值由函数调用时传入的实参
- 实参:实际参数,即调用时,需要传入的具体的值
- 注意:
- 声明式函数在定义之前,即可调用,因为js中会对声明式函数进行提升
- 参数的数量
- 形参比实参多:多余形参,由于在调用时没有给予具体的值,所以是undefined
- 实参比形参多:
- 拿到剩余的实参:通过函数天生自带的变量 arguments 可以获取到所有传递进来的实参
- arguments是什么?
- 是一个类似于数组结构的伪数组
- 我们可以通过索引(下标)来访问值
- 如果获取的下标不存在,得到的就是undefined
- 函数的 return
- 作用:返回结果(给出这个函数执行过后的返回值)
- 中断函数执行;
- 作用:返回结果(给出这个函数执行过后的返回值)
- 函数的作用域
- 什么是作用域?
- 就是一个变量可以生效的范围
- 变量存储在哪?
- 作用域
- 变量的值存在哪
- 内存中
- 栈内存:基本数据类型
- 堆内存:复杂数据类型
- 内存中
- 作用域的分类
- 全局作用域
- 局部作用域(函数作用域、私有作用域)
- 作用域中机制
- 变量的定义机制
- 你在该作用域中定义的变量,就是这个作用域下的私有变量
- 只能在该作用域中使用,或其后代作用域中使用
- 变量的赋值机制
- 当你给一个变量赋值时
- 先查找当前自己的作用域是否存在该变量
- 如果存在,直接进行赋值
- 如果不存在,那么就往父作用域中继续查找,直到找到为止,或最终找到全局作用域
- 如果到了全局作用域中都没有找到,在全局作用域中新创建一个全局变量
- 如果找到了则进行赋值
- 变量的访问机制
- 当你获取一个变量时
- 首先查找当前自己的作用域是否存在该变量
- 如果不存在,则开始向上在父作用域中查找,知道全局作用域
- 如果没找到,那么就会报错
- 如果找到了,则获取找到那个值。
- 变量的定义机制
- 什么是作用域?
- 提升(预解析)
- var 关键字定义的变量
- var关键字的提升,他只会把定义这个变量提升上去,赋值操作还停留原地。
- 所以提升之后,在赋值操作前去访问这个变量,得到的值是undefined
- 声明式函数
- 在所有代码执行之前,会把函数名进行提前声明,并且赋值
- 所以在声明式函数定义前面调用,不会报错,能够正常执行
- 重名问题
- 当使用var声明的变量与声明式函数 重名的时候。提升以函数为准。
- 只限于提升阶段。
- var 关键字定义的变量
- 递归函数(函数的一种应用方式)
- 递:一层一层的进去
- 归:一层一层的回来
- 把一件一件事情分成若干个事情来做
- 递归就是一个自己调用自己的手段
- 递归终点
- 当达到设置的终点时
- 再归回来,归通常使用 return
- 当没有终点的时候
- 就会陷入死循环,就会导致内存泄露
- 注意:递归慎用,能使用循环解决的,尽量不要使用递归。
- 声明式
- 定义阶段
对象
- 概念:是一个“盒子”,承载一些数据,里面的数据时无序的,是一个键值对的集合。
- 创建对象
- 字面量
- let obj = {}
- 内置构造函数
- let obj = new Object();
- 字面量
- 对象的操作
- curd
-
点语法
- 增:obj.键名 = 值
- 删除 delete obj.键名
- 改:obj.键名 = 值
- 查:obj.键名
-
数组关联语法
- 增:obj[“键名”] = 值
- 删:delete obj[“键名”]
- 改:obj[“键名”] = 值
- 查:obj[“键名”]
两种语法的区别:
- 点语法只能操作的是对象中的键名
- 数组关联语法,可以写入对象中的键名(以字符串的形式)。如果写入的不是字符串则会被识别为变量
- 对于特殊字符键名的curd
- 点语法在对一些特殊键名的对象数据操作时会报错
- 而数组关联语法则可以正常操作
- 对象的遍历
- 由于对象的数据结构是无序的,所以不能使用for循环来遍历
- for in方法遍历对象
- 语法:for(let 变量 in 要被遍历的对象){
声明的变量拿到的是键名
键值:被遍历的对象[变量]
}
- 语法:for(let 变量 in 要被遍历的对象){
-
数组
- 概念: 也是一个“盒子”,承载了多个数据的盒子,且内部的数据是有序的
- 序号:索引(下标)从0开始,依次+1
- 数组的创建
-
字面量
- let arr = [];
-
内置构造函数创建
- let arr = new Array();
- 数组的基本使用
- length:是一个可读写的属性
- 可以通过arr.length获取到当前数组的长度(数据的个数)
- 索引属性:是一个可读写的属性
- 读:通过索引获取到数组中对应索引位置上的数据
- arr[索引]
- 写:通过索引改写数组中索引对应位置上的数据
- arr[索引] = 值
- 读:通过索引获取到数组中对应索引位置上的数据
- length:是一个可读写的属性
- 数组的遍历
- 因为数组的索引是一组有规律的数字
- for循环也可以提供一组有规律的数字
- 所以可以直接使用for循环遍历数组
- for(let i = 0; i < arr.length;i++){
console.log(arr[i])// 拿到数组中每一项数据
}
- for(let i = 0; i < arr.length;i++){
- 数组方法
- push:向数组的末尾添加一条数据
- pop:删除数组中末尾的一条数据
- unshift:在数组的最前面添加一条数据
- shift:删除数组最前面的一条数据
- reverse:反转数组
- join:以传入的连接符,将数组的每一项拼接起来,组成一个字符串。
- 默认不传入参数,则以逗号作为了连接符拼接
- concat:拼接数组
- sort:对数组内的数据进行排序
- 不传递参数的情况下,以数据的每一项的unicode编码进行排序
- splice:截取数组并选择是否插入内容
- 截取
- 替换
- 截取并替换
- slice:截取数组
- 特点:包前不包后,可以写负数
- 参数:1、开始索引 2、结束索引
- 返回值:一个新数组,内容就是截取到的数据
- reduce:累加器
- 作用:遍历数组、累加、统计
- 语法:arr.reduce(function(初始值,当前项,当前项索引,当前被遍历数组){},初始值)
- 不定义reduce的第二参数,那回调函数中的第一参数的默认值是什么?
- 数组中的第一项数据
- 不定义reduce的第二参数,那回调函数中的第一参数的默认值是什么?
- indexOf:查找传入数据第一次出现在数组中的索引位置
- 没查到返回 -1
- 参数:两个,要查找的值,查找的开始索引
- lastIndexOf:从后往前查
- 返回值:和indexOf一样
- some:判断数组中是否有某一个数据满足条件
- 返回值:一个布尔值
- 如果有一个满足条件就为true
- 类似于逻辑运算符中的 ||
- 返回值:一个布尔值
- every:判断数:组中是否所有数据都满足条件
- 返回值:一个布尔值
- 如果都满足,则为true,否则false
- 类似于逻辑运算符中的 &&
- 返回值:一个布尔值
- forEach:遍历数组,拿到数组中的每一项、每一项的下标、被遍历数组
- filter:过滤数组
- 返回值:将满足条件的数据返回到一个新数组中。
- map:映射数组
- find:查找数组中的某一个数据
数组塌陷
- 在删除数组中数据的时候,就会发生塌陷
- 解决
- 倒着循环数组
- 让i也跟着变化
-
数组去重
- 七种方法(熟读,至少掌握三种)