操作符
撰写时间:2024-01-27
修订时间:2024-12-03
in
如果属性存在于特定对象及其prototype链中,in操作符返回true
。
对象
这与for let in
语句的作用相似,但for let in
语句返回的属性名称中不包含不可列举的属性名称。
结果:
toString方法属于prototype链中Object.proptype中的方法,属于不可列举的属性,因此不出现在遍历结果中。详见遍历prototype链中所有属性。
数组
在JavaScript中,数组的类型是也object。
作为对象,数组元素的索引值就是属性名称。
显示:
当in操作符应用于数组中,经常犯的错误是:
in操作符只与对象的属性打交道,而数组元素的值不是对象属性名称!
作为对象,arr具有下列属性:
因此,除了使用数组索引值访问数组元素之外,我们也可以使用数组属性名称来访问数组元素。
因此,当in操作符应用于数组时,正确的代码应是:
上面,字符串2
是arr的属性名称。而数组更进一步,连索引数值也可作为属性名称使用:
对于上面的代码,我们可以理解为:数组arr是否有2
这个属性名称,或者也可理解为数组arr是否有第2个元素?
而当数组元素类型正好也是整数型时,这很容易带来混乱:
一句话,当in操作符应用于数组时,我们只能使用数值元素索引值或其相应的字符串来进行测试,不能使用数组元素的值来进行测试。
Falsy及Truthy
在需要确定Boolean值的场合下,一个falsy值是指其值为false。
以下为falsy:
- null
- undefined
- false
- NaN
- 0
- -0
- 0n
- "", '', ``: 空字符串
- document.all
上面,null及undefined属于nullish(空值)。正如上面,nullish值总为falsy。
而非falsy值即为truthy。
在中文环境下,当谈到布尔值的假值
时,我们想到的最多的是false
, 0
,但除了这两个常见的值之外,在JavaScript中,上面的全都是中文环境下的假值,也即falsy。
依空返回操作符 (??)
依空返回操作符(Nullish Coalescing Operator,??
)根据一个变量是否空值而返回不同的值。其语法为:
如果x值为null
或undefinded
,则返回右边的y的值;否则,返回左边的x的值。相当于:
下面为常见的例子:
意为,如果x为空值(nullish),则num被赋值为50
。而如果x的值不为空值,则num被赋值为x的值。
更容易的理解为:我们准备根据x是否空值的情况来赋值。如果x为空值,则赋值一个默认值;否则,取自x的值。
注意与下面的代码区分:
当x的值为0
时,它的值虽然为false
,但已经不再是nullish,因此,num被赋值为0
。
依空赋值操作符 (??=)
上面根据判断一个变量是否为空值来给另一个变量赋值,而如果根据一个变量为否为空值来决定该变量的值时,则可使用更方便的依空赋值操作符(Nullish Coalescing Assignment,??=
)。
相当于:
这种情况下,如果变量的值不为空值,则没有任何额外的赋值动作。
可以理解为:拒绝空值(nullish guarding)。如果为空值,则赋于一个默认值。
??=
操作符经常用于为类型为对象的函数参数提供全方位的默认值:
listConfig函数希望传入的实参options中包括足够的信息,但又必须让客户端灵活地只挑选其认为最重要的选项,未提供的可取自默认值。
上面客户端的实参只设定了name的值,而在listConfig函数中,数据不全可能造成程序无法运行,故在该函数内部,对每一个必要的选项均使用??=
操作符进行了补充性的默认值设置。
结果输出:
但这种方法有点小问题,如果客户端很懒,其实参为空值呢?
程序将抛出异常,因为参数options为空值,我们不能在空值上引用各个属性名:
解决的方法有3种。第一种是在使用带有默认值的函数参数:
第二种解决的方法是在函数体内的前面添加一个空值判断赋值语句:
代码:
先判断参数options是否为空,若为空值,则先为其赋值于一个空对象。下面再进一步为这个空对象设置各个属性值。
第三种解决的方法是使用解构。
这种代码显得很紧凑、美观。唯一需注意的是,使用解构时,实参options可能不是完整的,但在使用默认值解构过程中,我们得到了所有必要的变量。
可选链操作符
可选链接操作符(optional chaining operator,?.
)可在特定对象存在时才调用其特定方法。
如果页面上不存在element这个对象,则不会调用addEventListener方法。只有在该对象存在时才会调用。其效等于:
展开操作符
展开操作符(Spread operator)的作用在于,将一个可遍历对象(iterable object)的各个子元素分别提取为独立的多个个体。这个可遍历对象可为数组,字符串,或Object。简而言之,将一拆分为多。语法为:
数组元素
展开
数组中的3个元素,被提取出为独立的3个整数。
但不能这样使用:
...arr
是独立的3个整数,不能赋值于单一变量。
函数参数
arr展开为3个整数,作为实参依序传递给listArgs函数。
数组字面符
数组字面符支持展开操作符,这使得数组操作更加容易、直观。
数据展开方式是浅复制的方式。
展开a后,b数组中的每个元素都是a数组的子元素的数组对象引用。因此,当a数组的子元素的值发生改变时,也将影响到b数组的值。
对象字面符
对象字面符中可支持展开操作符。
当两个具有相同属性名称的对象合并时,后面对象的属性值将覆盖前面对象的属性值。
字符串字面符
字符串字面符也支持展开操作符。
这个结果为何这么奇怪?
JavaScript引擎在展开字符串时,是将字符串当作对象来展开的。等同于下面代码:
根据上节,只要是属性名称相同的值,都会被后面对象的值覆盖。因此就出现了上面的结果。类似于蒙板效果,将a覆盖在b上面,b只有比a长的部分才会露出来。
操作符分类
增加及减少操作符
- A++
- 后缀增加操作符
- A--
- 后缀减少操作符
- ++A
- 前缀增加操作符
- --A
- 前缀减少操作符
一元操作符
- delete
- 删除操作符,用以从对象中删除属性
- void
- 计算表达式并废弃其返回结果
- typeof
- 返回特定对象的类型
- +
- 一元加号操作符将操作数转换为Number型
- -
- 一元减号操作符将操作数转换为Number型后取反
- ~
- 位域取反
- !
- 逻辑取反
- await
- 暂停并恢复一个async函数,并等待Promise的完成或拒绝。
算术操作符
- **
- 幂
- *
- 乘以
- /
- 除以
- %
- 求余
- +
- 加
- -
- 减
关系操作符
- <
- 小于
- >
- 大于
- <=
- 小于等于
- >=
- 大于等于
- instanceof
- 返回某个对象是否其他对象的实例
- in
- 对象是否具有特定属性
相等操作符
- ==
- 等于
- !=
- 不等于
- ===
- 严格等于
- !==
- 严格不等于
位域移动操作符
- <<
- 位左移
- >>
- 位右移
- >>>
- 位无符号右移
二进制位域操作符
- &
- 位与
- |
- 位或
- ^
- 位异或
逻辑操作符
- &&
- 与
- ||
- 或
- !
- 非
- ??
- 依空返回操作符(nullish coalescing operator)
三元条件操作符
- (condition ? ifTrue: ifFalse)
- 当前置条件为真时,返回第1个结果;否则,返回第2个结果。
赋值操作符
- =
- 赋值操作符
- *=
- 乘以赋值操作符
- /=
- 除以赋值操作符
- %=
- 求余赋值操作符
- +=
- 相加赋值操作符
- -=
- 相减赋值操作符
- <<=
- 左移赋值操作符
- >>=
- 右移赋值操作符
- >>>=
- 无符号右移赋值操作符
- &=
- 位与赋值操作符
- ^=
- 位异或赋值操作符
- |=
- 位或赋值操作符
- **=
- 幂赋值操作符
- &&=
- 与赋值操作符
- ||=
- 或赋值操作符
- ??=
- 依空赋值操作符(nullish coalescing assignment)
- [a, b] = arr, {a, b} = obj
- 解构赋值操作符
Yield操作符
- yield
- 暂停并恢复一个生成器函数
- yield*
- 交由另一个生成器函数或可遍历对象代理
展开操作符
- ...obj
- 将一个可遍历的对象,如数组或字符串,拆分为多个独立个体。
逗号操作符
- ,
- 逗号操作符允许多个表达式并存于一个语句,且返回最后一个表达式的结果。
可选链操作符
- ?.
- 访问对象属性或调用函数。