准确理解 JS 的 ++ 运算符
对于刚开始接触前端开发的朋友们来说,可能地一个令人苦恼的问题是关于运算符 ++ 的计算,特别是它还有前置与后置的区别。当它们和一堆运算在一起的时候,常常令人头晕目眩!
我经常性地称它是一个***难人的问题,因为它本身所发生的操作又是十分的简单——加 1。是的,++ 运算符的唯一计算操作就是给它的操作数加 1。然而,它到底是怎么加的 1 呢?就我而言,我一直都觉得这很神奇,它应该是使用了某种魔法吧!
拨开层层迷雾,在你看见了它的庐山真面目后,你又会惊讶于它是如此的简单纯粹。这一切,都要从最基本的概念——表达式说起。
什么是表达式?表达式是对一个变量或值的引用,或是一组值和变量与运算符的组合。
举例来说,像 1、2 这样的字面值就是一个表达式,尽管它没有多大意义。我们更经常接触的表达式是像 1 + 1 这样的,值与运算符的组合。
表达式的本质是值。分两点来说,一是我们使用表达式的真正目的是要取得它背后的值;二是一个表达式总是会运算并返回一个值。比如,1 + 1 和 2 是等价的,在使用 1 + 1 这个表达式的地方,我们都可以把它换成值 2。这在计算机中之所以成立,是因为 1 + 1 这个表达式它总是会运算并返回值 2。试想一下,如果表达式 1 + 1 没有被计算,它怎么能和值 2 相等呢?
所以,1 + 1 和 2 是等价的准确说法,应该是表达式 1 + 1 的返回值和值 2 是等价的,它们是相等的。尽管前者的概念是表达式,后者的概念是值。
我们再来看一个例子:
let a = 1;
let b = a + 1;
请问这里的变量 b 等于多少?要正确的回答这个问题,你得知道在 a + 1 这个表达式中变量 a 也是一个表达式。所以,我们首先得知道表达式 a 的值是多少,然后将它和 1 相加。表达式和表达式可以通过运算符组合在一起,得到一个新值。这里,表达式 a 的值就是变量 a 引用的值 1。
再来看一个例子:
let a = 1;
let b = (a = 2) + 1;
请问这里的变量 b 又等于多少呢?或者说表达式 (a = 2) + 1 的值是多少?你可能发现了,关键点是要知道表达式 a = 2 的值是多少。
这里就引出了表达式的另一个重要内涵——副作用。表达式的副作用是指表达式在返回值的过程中对别处的值也产生了影响。赋值表达式的副作用就是将某个值赋给了变量,或者说它更换了变量中的值。在 (a = 2) + 1 中,赋值表达式 a = 2 会先给变量 a 赋值 2,然后返回这个变量的值。所以,这里表达式 a = 2 的返回值便就是 2。
有了上面这些概念后,你对前 ++ 和后 ++ 的区别就会有着很好的理解。
这里顺带补充一点,++ 运算符只能和变量一起使用。也就是说,++ 运算符的操作数必须是一个变量,因为它需要一个容器(变量)来承接它的副作用。
前 ++ 和后 ++ 的关键区别就在于它们对操作数执行加 1 的操作的时机点不同。前 ++ 是在返回表达式值之前就对操作数进行了加 1 的运算,后 ++ 则是在返回表达式值之后再对操作数执行加 1 的操作。
举例来说:
let a = 1;
let b = (a++) + 1 + a + (++a) + a + 1;
请问这里的变量 b 又会是等于多少呢?关键点就在 a++ 和 ++a 这两个表达式的值是多少!
a++ 是一个后 ++ 表达式,后 ++ 的副作用发生在它返回表达式值之后。所以,这里 a++ 会先返回表达式 a 的值。所以,这里表达式 a++ 的返回值就是变量 a 的直接引用值 1。
那么紧接在 a++ 后面的那个变量 a 又会是等于多少呢?是 2。因为,前面的 ++ 操作已经给 a 加了 1。所以,这里表达式 (a++) + 1 + a 等价于 1 + 1 + 2。
注意体会这里的操作,这个地方发生且仅发生了两件事:第一件事是返回变量 a 引用的值,第二件事是给变量 a 执行加 1 的运算。这就是为什么后面的 a 会是 2 的原因了,因为这时的 a 已经被加了 1。
++a 是一个前 ++ 表达式,前 ++ 的副作用发生在它返回表达式值之前。也就是说,前 ++ 表达式得到的值是 ++ 运算符执行计算后的结果值。所以,这里表达式 ++a 的值是 3。
所以,这里表达式 (a++) + 1 + a + (++a) + a + 1 等价于 1 + 1 + 2 + 3 + 3 + 1,最终计算结果为 11。
最后,和 ++ 对应的 -- 运算符的运算规则和 ++ 是完全一致的,只不过它的操作是对操作数执行减 1 的运算。
准确理解 JS 的 ++ 运算符的更多相关文章
- 从一个简单例子来理解js引用类型指针的工作方式
<script> var a = {n:1}; var b = a; a.x = a = {n:2}; console.log(a.x);// --> undefined conso ...
- js对象详解(JavaScript对象深度剖析,深度理解js对象)
js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...
- 好程序员web前端分享如何理解JS的单线程
好程序员web前端分享如何理解JS单线程,JS本质是单线程的.也就是说,它并不能像JAVA语言那样,两个线程并发执行. 但我们平时看到的JS,分明是可以同时运作很多任务的,这又是怎么回事呢? 首先,J ...
- 10分钟理解JS引擎的执行机制
首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 (1) JS为什么是单线 ...
- 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)
首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...
- 深入理解JS this,作用域
深入理解JS this 阮一峰博客链接http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html this ...
- 【学习笔记】深入理解js原型和闭包(5)——instanceof
又介绍一个老朋友——instanceof. 对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/ ...
- 【学习笔记】深入理解js原型和闭包(1)—— 一切都是对象
“一切都是对象”这句话的重点在于如何去理解“对象”这个概念. ——当然,也不是所有的都是对象,值类型就不是对象. 首先咱们还是先看看javascript中一个常用的运算符——typeof.typeof ...
- 理解JS引擎的执行机制
首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 : JS为什么是单线程的 ...
- 深入理解JS引擎的执行机制
深入理解JS引擎的执行机制 1.灵魂三问 : JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4 ...
随机推荐
- 获取不同型号手机小程序导航栏的高度(uniapp)
uni.getSystemInfo({ success: function(e) { Vue.prototype.StatusBar = e.statusBarHeight; let custom = ...
- Airtest使用问题列表
ios 系统为12.4.8,因此安装Xcode 10.3; 问题1: python3: error: unable to find utility "python3", ...
- RPC简介及框架选择-copy
简单介绍RPC协议及常见框架,对比传统restful api和RPC方式的优缺点.常见RPC框架,gRPC及序列化方式Protobuf等 HTTP协议 http协议是基于tcp协议的,tcp协议是流式 ...
- T480指纹识别支持
目标 通过指纹识别解锁slim-lock 环境 操作系统archlinux 桌面管理器slim 锁屏slimlock 硬件 Thinkpad T480 注: 指纹设备id, 06cb:009a 安装 ...
- el-table合计行
用到属性 showSummary 是否显示合计,方法 summaryMethod 计算合计的自定义方法. <el-table ref="elTable" :data=&quo ...
- 在Windows系统中安装Open WebUI并连接Ollama
一.Open WebUI简介与安装前准备 Open WebUI是一个开源的大语言模型(LLM)交互界面,支持本地部署与离线运行.通过它,用户可以在类似ChatGPT的网页界面中,直接操作本地运行的Ol ...
- 探秘Transformer系列之(2)---总体架构
探秘Transformer系列之(2)---总体架构 0x00 概述 0.1 流程 使用Transformer来进行文本生成其实就是用模型来预测下一个词,完整流程包括多个阶段,如分词.向量化.计算注意 ...
- [ABC259F] Select Edges 题解
很容易想到树形 dp. 考虑在有根树内,每个点都有两种状态: 不选自己和父亲的边: 要选自己和父亲的边. 那么单独对于子树内部而言,就要分两种情况: 最多可以向 \(d_i\) 个孩子连边,对应上述第 ...
- C# List LinQ Lambda 表达式
------------恢复内容开始------------ # 参考链接 : https://blog.csdn.net/wori/article/details/113144580 首先 => ...
- 八米云高收益PCDN-N1设备重要通知
八米云单价: 电联2400元/G/月 移动1500元/G/月 新上机设备[必须使用新镜像]上机!否则无业务下发! 再次强调!如6.18日后台镜像更新后–还在使用旧镜像新上机,请务必于[6月30日]前用 ...