前端JavaScript基础训练系列一百二十三:表达式的副作用

大部分表达式没有副作用。例如:

    var a = 2;
     var b = a + 3;

表达式a + 3本身没有副作用(比如改变a的值)。它的结果值为5,通过b = a + 3赋值 给变量 b。
最常见的有副作用(也可能没有)的表达式是函数调用:

    function foo() {
         a = a + 1;
}
var a = 1;
foo(); // 结果值:undefined。

副作用:a的值被改变 其他一些表达式也有副作用,比如:

    var a = 42;
     var b = a++;

a++ 首先返回变量 a 的当前值 42(再将该值赋给 b),然后将 a 的值加 1:

var a = 42;
var b = a++;
     a;  // 43
     b;  // 42

很多开发人员误以为变量 b 和 a 的值都是 43,这是因为没有完全理解 ++ 运算符的副作用 何时产生。
递增运算符 ++ 和递减运算符 – 都是一元运算符,它们既可以用在操作数的 前面,也可以用在后面:

var a = 42;
     a++;    // 42
     a;      // 43
     ++a;    // 44
     a;      // 44

++ 在前面时,如 ++a,它的副作用(将 a 递增)产生在表达式返回结果值之前,而 a++ 的 副作用则产生在之后。
++a++ 会产生 ReferenceError 错误,因为运算符需要将产生的副作用赋值给 一个变量。以 ++a++ 为例,它首先执行 a++(根据运算符优先级,如下),返 回 42,然后执行 ++42,这时会产生 ReferenceError 错误,因为 ++ 无法直接 在 42 这样的值上产生副作用。
常有人误以为可以用括号 ( ) 将 a++ 的副作用封装起来,例如:

var a = 42;var b = (a++);
     a;  // 43
     b;  // 42

事实并非如此。( )本身并不是一个封装表达式,不会在表达式a++产生副作用之后执行。 即便可以,a++ 会首先返回 42,除非有表达式在 ++ 之后再次对 a 进行运算,否则还是不会 得到 43,也就不能将 43 赋值给 b。
但也不是没有办法,可以使用 , 语句系列逗号运算符(statement-series comma operator)将多个独立的表达式语句串联成一个语句:

var a = 42, b;
b = ( a++, a );
a;  // 43
b;  // 43

由于运算符优先级的关系,a++,
a 需要放到 ( … ) 中。本章后面将会介绍。
a++, a 中第二个表达式 a 在 a++ 之后执行,结果为 43,并被赋值给 b。
再如 delete 运算符。第 2 章讲过,delete 用来删除对象中的属性和数组中的单元。它通
常以单独一个语句的形式出现:

var obj = {
    a: 42
};
obj.a;
delete obj.a;
obj.a;
// 42
// true
// undefined

如果操作成功,delete 返回 true,否则返回 false。其副作用是属性被从对象中删除(或 者单元从 array 中删除)。
操作成功是指对于那些不存在或者存在且可配置的属性, delete 返回 true,否则返回 false 或者报错。
另一个有趣的例子是 = 赋值运算符。 例如:

var a;
     a = 42;     // 42
     a;          // 42

a = 42中的=运算符看起来没有副作用,实际上它的结果值是42,它的副作用是将42赋 值给 a。
组合赋值运算符,如+=和-=等也是如此。例如,a = b += 2首先执行b += 2(即 b = b + 2),然后结果再被赋值给 a。
多个赋值语句串联时(链式赋值,chained assignment),赋值表达式(和语句)的结果值就 能派上用场,比如:

    var a, b, c;
     a = b = c = 42;

这里c = 42的结果值为42(副作用是将c赋值42),然后b = 42的结果值为42(副作用 是将 b 赋值 42),最后是 a = 42(副作用是将 a 赋值 42)。
链式赋值常常被误用,例如var a = b = 42,看似和前面的例子差不多,实 则不然。如果变量b没有在作用域中象var b这样声明过,则var a = b = 42 不会对变量 b 进行声明。在严格模式中这样会产生错误,或者会无意中 创建一个全局变量。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值