表达式是js中的一个短语,通常我们会通过运算符讲简单表达式组合成复杂表达式,而语句是js整句或命令,JavaScript程序可以理解为一系列可执行语句的集合
表达式
-
原始表达式
表达式的最小单位,包含常量或者字面量,关键字和变量
-
对象和数组的初始化表达式
实际上是新创建的对象和数组
-
函数自定义表达式
var func = function(x){/*函数体 */}
-
属性访问表达式
expression.identifier
expression[expression]
不管哪种形式,’.‘和’['之前的表达式总会首先计算,如果结果是null或者undefined,系统会抛出异常
-
调用表达式
func(x)
一种调用(或者执行)函数或方法的语法表示。
如果函数使用return语句给出一个返回值,那表达式的结果就是这个返回值,否则就是undefined
如果圆括号之前的表达式是一个属性访问表达式,这个调用被称为方法调用,在方法调用中,执行函数体室,作为属性访问主题的对象和数组便是其调用方法内this的指向
-
对象创建表达式
创建一个对象并调用一个函数(这个函数被称为构造函数)
new Object()
如果没有入参,括号可以省略
运算符
-
一元运算符
-
a++,++a,a–,--a
-
+a(可以用来将字符串转换为数字),-a
-
delete 删除对象属性或数组元素
不能删除不可配置的属性,不能删除var,let,const声明的属性,只会删除自有属性
-
void 对给定的表达式进行求值,不管操作数如何计算,最后结果都会返回undefined
箭头函数标准允许函数体不使用括号直接返回值,如果右侧调用了一个没有返回值的函数,其返回值改变之后就会产生非预期的副作用,这个时候就可以用void,不管发生什么,最后都返回undefined。
-
typeof
放在任意类型的操作数前面,返回表示操作数类型的一个字符串
null和数组都会返回’object’,所以用typeof来区分数组和对象是不可行的
-
~ 按位求反
-
!将操作数的布尔值进行求反
-
-
算术运算符
-
+,-,*,/,%(取余)
比较特殊的’+’,它有时也可以用来起到字符串连接的作用,如果其中一个操作数是字符串,另一个操作数也会转换成字符串,进行拼接操作,否则进行数字加法操作(null变成0,布尔值转换为对应的0和1
true+null //1
)
-
-
关系运算符
-
in
如果指定的属性在指定的对象或其原型链中,返回true,否则返回false(只要有在里面,不管有没有赋值,或者赋值为undefined/null,都返回true)
-
instanceof
左操作数是一个对象,右操作数标识对象的类,用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上。
多全局对象场景下,instanceof可能会出问题,比如网页中包含多个框架,那么每个框架就会有自己的一套全局执行环境,对于数组而言,就会拥有多个不同版本的Array构造函数,这时从其中一个框架向另一个框架传入一个数组,数组和b中创建的数组就会拥有不用的构造函数
-
‘>’,’<’,’>=’,’<=’
其中一个操作数是NaN的时候,这四个操作符都返回false
-
-
相等运算符
-
‘==’ /’!=’
操作数类型相同时按照全等比较规则进行
操作数类型不一样的时候也可能会相等
- null == undefined
- 如果一个数字一个字符串,会先将字符串转换为数字,然后再进行比较
- 如果是布尔值,会先转换为对应的数字再进行比较
-
’ === ‘/’ !== ’
- 两个值类型不同,不相等
- NaN不相等(这货独一无二,连自己都不等于自己)
- null===null,undefined === undefined
- true===true,false === false
- 数字的全等(特殊:0===-0,Infinity === Infinity)
- 字符串对比的时候,需要包含位上的16位数都完全相等才会全等,如果编码不一样,是不相等的(和=都不等,需要通过LocaleCompare来判断)
- 引用值需要指向同一个对象才相等,不然就算属性和属性值都完全一样,但是它们不指向同一内存空间,都视为不等
-
-
位运算符
- & 进行布尔与(AND)运算
- | 进行布尔或(OR)运算
- ^ 按位异或(XOR)运算(只能有一个true,同时1或者同时0都不行)
- ‘<<’ 左移
- ‘>>’ 右移(带符号位),第一个操作数是正数,最高位补0,是负数,补1
- '>>>'右移(不带符号位),左边最高位一直都补0
-
赋值运算符
- =,*=,/=,%=,+=,-=,>>=,<<=,>>>=,&=,^=,|=
-
逻辑运算符
-
&&
运算符会先计算左操作数的值,如果是false,直接返回false,是true将右操作数的结果返回(这种行为被称为短路)
-
||
运算符会先计算左操作数的值,如果是true,返回左操作数,如果是false,返回右操作数的结果
- ??
当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数 - ?.
允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效
- ??
-
-
其他
-
条件运算符
a===b ? a:b
第一个表达式结果为true,执行第二个表达式并返回其结果,否则执行第三个表达式并返回其结果,这个可以理解成简单的if-else语法糖 -
扩展运算符
在函数调用/数组构造时,将数组表达式或者string在语法层面展开,在构造字面量对象时,将对象表达式按key-value的方式展开
const arr = [1,2,3,4,5] const arr1 = [...arr, 6,7,8] // [1,2,3,4,5,6,7,8] const obj = {a:1,b:2,c:3}; const obj1 = {...obj,c:5,d:4}; // {a:1,b:2,c:5,d:4} c为5的原因是对象发现有相同属性的值时,后面的值会将前面的值进行覆盖 // 扩展运算符与Object.assign()行为一致,执行的事浅拷贝
-
逗号运算符
先计算左操作数,再计算右操作数,最后返回右操作数的结果
-
语句
-
控制流程
-
block
用于组合零个或多个语句,用大括号界定,形成一个块,用var声明的变量时没有块级作用域的,用let,const声明的才有,所以现在一般建议用let和const声明变量
-
break
中止当前循环,switch语句或者label语句,并把程序控制流转到紧接着被中止语句后面的语句中
不能在函数中直接使用,需要嵌到循环或者switch,label语句当中
break [label]
label标识符是可选的,表示中止当前被标记的语句,继续往下走 -
continue
终止当前循环或者标记循环的当前迭代中的语句执行,在下一次迭代中继续执行循环
break可能就直接整个循环都跳出来了,continue只是把当前循环跳过,进行下一次循环,同样的,也可以带可选择的标识符
-
Empty
用
;
表示没有语句 -
if…else
else if可以无限嵌套,最后以else结尾,表示除之前状态外的所有状态
if(condition1){ statement1 }else if(condition2){ statement2 } else { statement3 }
-
switch
评估一个表达式,将表达式的值与case子句匹配,并执行与该情况相关联的语句
switch(type){ case condition1: statement1; break; case condition2: statement2; break; default: // 类似最后的else,但位置放哪里都有效 statement3; break; } // 和上面的if...else相等 // 不加break的话它会一个个case去匹配,就算找到匹配的,还是会接着往下走,也可以用return终止查找
-
throw
抛出用户定义的异常,并将控制传递到调用堆栈的第一个catch块中,如果没有catch,程序将会被终止
-
try…catch…finally
try当中执行遇到问题,就会抛出到catch当中,finally语句在try和catch之后,不管最后结果是执行成功还是有错误,都会执行finally子句
如果从finally块中返回一个值,这个值会成为整个
try...catch...finally
的返回值,也无论try或者catch里面有没有return或者有没有错误,统统都没有finally返回值重要
-
-
迭代器
-
while
在某个表达式为真的前提下,循环执行某一段代码,直到表达式不为真时停止,先检查表达式,再执行代码
while(condition){ statement; }
-
do…while
先执行代码,然后再检测表达式是否为真,所以循环至少会执行一次
do statement; while (condition)
-
for
下一次condition执行之前执行final-expression
for(initialization;condition;final-expression){ statement }
-
for…in
无序遍历对象的可枚举属性,语句针对每个唯一的属性
-
for…of
遍历可迭代的对象,对不同属性的属性,调用一个自定义的有执行语句的迭代钩子
-
-
其他
-
with
扩展一个语句的作用域链(不建议使用)
-
label
标记就是在一条语句前面加个可以引用的标识符,这样break和continue就可以引用
-
debugger(不用解释了吧,用来调试用的)
-
export
用来导出函数,以便这些函数能够被导入到外部模块或其他脚本中
-
import
用来引入外部的模块或另一个script中导出的函数
-