[TOC]
控制流
控制流的底层
start=>start: 开始
cond1=>condition: 判断
sub1=>subroutine: 子程序
op1=>operation: 程序
end=>end: 结束
start->cond1
cond1(yes)->op1->end
cond1(no)->sub1(top)->cond1
while循环
- 只要条件满足,会不断重复执行
块语句
块语句
- 也称为
复合语句
- 花括号包裹的一系列语句得集合
- 不是控制流语句
- 和控制流结合使用
空格
辅助方法
if else语句
do…while循环
for循环
if语句
控制流异常
- break提前结束循环
- continue循环跳到下一步
- return退出当前方法
- throw指出必须被异常处理器所捕获的异常(包括超出当前控制流得异常)
switch语句
for…in循环
是为了那些循环对象中有一个属性key而设计的
for(变量 in 对象){
语句
}
const player = {name: 'Thomas',
rank: 'Midshipman',
age: 25} ;
for(let prop in player){
if(!player.hasOwnProperty(prop)) continue ;
console.log(prop + ':' + player[prop]) ;
}
for..of循环(ES6)
另一种在集合中遍历元素的方法
for(变量 of 对象)
语句
- 可以遍历任何
可迭代
的对象 - 遍历数组,又不需要知道每个元素的索引的最佳选择
const arr = [ 'a', 'b', 'c'] ;
for(let it of arr){
alert(`arr的元素有${it}`) ;
}
实用的控制流模式
使用continue减少条件嵌套
//典型的嵌套控制流
//num 是 randomNum()产生的随机数
while(num > 1 && num < 100){
if(num === 7){
alert('lucky you') ;
}
else{
num = randomNum() ;
}
}
//使用contionue使结构更加「扁平」
while(num > 1 && num < 100){
if(num === 7){
alert('lucky you') ;
continue ;
}
num = randomNum() ;
}
使用break或return 避免不必要的计算
循环结束后使用索引的值
循环一个列表同时还在修改它,常用做法使用索引递减的循环方式
表达式和运算符
-
表达式是一种特殊的语句
- 对生成的结果做显式的转换
- 能解析成值,所以可以和其他表达式组合在一起
- 可以用来赋值
let x ; x = 3 * 5 ; //第一个运算符表达式3 * 5 ,返回结果15 //第二个赋值表达式x = 15 ,返回结果就是所赋的值
- 非表达式语句
运算符
- 运算符是表达式的"动作"
- 运算符使用1个以上的操作数进行运算
算数运算符
JavaScript中所有的数字都是双精度的,所以算数运算可能返回小数
运算符优先级
比较运算符
-
严格相等
===
两个值引用了同一个对象,或拥有相同类型的相同值
非严格相等
==
比较数字
-
NaN与任何值都不想等,包括它自己
- 可以使用内置函数
isNaN(数字)
判断某个数字是否是NaN,返回布尔值
- 可以使用内置函数
-
小数比较最好使用关系运算符测试它是否足够接近目标
JavaScript中有个数字常数
Number.EPSILON
,1和比1大且最接近于1的数之差。const a = 0.1 , b = 0.2 , c = 0.3 ; //num 不为0 ,实际值是5.551115123125783e-17 let num = a + b - c ; //如果直接 a+b === c 这样比较就会返回false //将a+b 和 c 的差num与Number.EPSILON相比 if(num < Number.EPSILON ) alert(`a+b等于c`) ;
字符串连接+
JavaScript会根据运算对象的类型来决定执行加法 还是字符串连接
逻辑运算符
-
假
- undefined
- null
- false
- 0
- NaN
- ''空字符串
-
真(除了"假"的其他值)
空数组也为真
与或非
短路求值
const bool1 = true ;
let a = 0 ;
//或运算,第一个为真,短路,之后的a++不执行。
const result1 = bool1 || a++ ;
const bool2 = false ;
let b = 0 ;
//且运算,第一个为假,短路,之后的b++都不执行
const result2 = bool2 && b++ ;
非布尔值的逻辑运算
- 使用布尔值做运算,结果只能是布尔值
- 非布尔值做运算,能确定结果的值就是逻辑运算的结果
- 使用了
!
非运算符,永远返回布尔值
条件运算符(三元运算符)
const bool = false ;
const message = bool ? "有消息了" : "没有消息" ;
//等价于使用if...else
if(bool){
const message = "有消息了" ;
}
else{
const message = "没有消息" ;
}
逗号运算符
优先级
最低
-
它会按顺序执行多个表达式,但是只返回最后一个表达式的结果。
const a = 1 , b = 2 , c = 4 ; const d = (a + b , b + c , a + c ) ; alert(d) ;//5
分组运算符()
位运算符
类型判断运算符typeof
表达式 | 返回值 | 备注 |
---|---|---|
typeof null | "object" | |
typeof Symbol() | "symbol" | ES6 |
... | ... | ... |
void运算符
计算操作数并返回undefined,没什么用,唯一的用途是作为HTML标签<a>的URI
<a href="javascript: void 0">lol</a>
赋值运算符
-
链式赋值
let a, b ; a = b = 1 ;
-
优先级低于关系运算符
const a = 1; let n , m; n = a < 0 ; (m = a) < 0 ; console.log(n) ;//false console.log(m) ;//1
解构赋值(ES6)
允许将对象或数组分解成多个单独的值
-
变量名必须与对象中的属性名保持一致
const obj = { name : 'Bob' , age : 25 , color : "red" , number : 001 } ; //多个address,少了个number; const { address, name, age, color } = obj ; address;//undefined name;//'Bob' age;//25 color;//'red' number;//error,未定义
-
声明和赋值也可以分开,但是需要在赋值的时候使用
()
括起来// const 声明需赋值,所以此处换成let let address, name, age, color; ({address, name, age, color} = obj ) ;
数组解构只能指派标识符得属性名
-
…
展开运算符,可以将数组剩下的元素放入一个新的数组const arr = [1, 3, 5, 6, 7, 8, 10] ; let [one, three, five, ... other] = arr ; one;//1 three;//3 five;//5 other;//[6, 7, 8, 10]
-
数组解构可以方便交换变量的值
let a = 1 , b = 0 ; [a, b] = [b, a] ; a; //0 b; //1
对象和数组运算符
运算符 | 描述 |
---|---|
. | 成员访问 |
[] | 计算机成员访问 |
in | 判断属性是否存在 |
new | 实例化对象 |
instanceof | 原型链测试 |
... | 展开运算符 |
delete | 删除运算符 |
模板字符串中的表达式
表达式和控制流模式
- if…else语句转化成条件表达式
if(bool){
message = '有' ;
}
else{
message = '无' ;
}
//转化成表达式
message = bool ? '有' : '无' ;
- if语句转化成短路求值的逻辑或表达式
if(!options) options = {} ;
//转化
options = options || {} ;