话不多说,开始今天的码字之旅。

突然有种日更小说的感觉,emm...

操作符

ECMAScript(JS核心)描述了一组用于操作数据值的操作符,也包括算术操作符等等

而JS中这些操作符最鲜明的特点就是,可以适用于多种数据类型。

对于Object类型,通常会调用toString()或valueOf()方法以便运算符能够操作。

一元操作符

顾名思义,只能操作一个值的操作符叫做一元操作符

JS中这样的操作符有两类

1.  递增递减操作符

2.一元加(减),即常用的正负号

  • 递增递减操作符

JS中的递增递减操作借鉴自C,且都拥有两种类型前置、后置。

这两种操作符相信大家应该都不陌生。

前置、后置的区别往往就在于一个是运算之前值就已经加一了,后置往往是运算完成后才加一或减一;

那么这两种操作符是如何实现的呢?

前置的很简单,直接将数加一就行,那后置的呢?

大概流程是这样的:

先创建一个该变量的副本,然后将这个变量+1(-1),让变量的副本参与运算,这样就能实现后置递增

这些与C中的都差不多,但是最大的区别在于,JS这些运算符不仅仅能用于整数。

还可以应用于其他数据类型,而且不用像C++那样重载运算符。(当然由于JS的限制也不能重载emm)

对于其他类型的数据,递增递减操作符遵循以下规则:

1.对于包含有效数值的字符串,会先将该字符串转为数值,然后对该数值进行运算(即有效的字符串处理后会变成数值变量)

2.对于不包含有效数值的字符串,将值设为NaN,并将变量变为数值变量

3.对于Boolean类型,会先将true,false转为数值0、1然后进行运算

4.对于浮点数类型,会只对整数部分进行操作

5.对于Object,先调用valueOf,若返回值为NaN,然后调用toString

即相当于会先使用Number()对所有的值进行类型转换后再进行相应操作,具体操作见前文

  • 一元加、减

这个操作符的作用除了用于转换数值的正负之外,还可以用于数据类型的转换。

因为在转换正负之前,会先对数据使用Number()进行数据转换

转换规则与上方一致,具体操作见前文

位操作符

位操作是一个给人感觉很高大上的东西,许多的面试题也喜欢出。

这里我不讲骚操作(我也没整明白emm...),只讲一下JS中位操作的规则,以及和其他语言的一些区别

前面我提过,JS的数值都以IEEE-754标准的64位格式存储,但是整数是32位。

所以在JS中位操作不会直接操作64位的值,会先将64位的值转为32位整数,进行位操作后转回64位

这样的操作会带来一个严重的副效应,即NaN和Infinity使用位操作时会被当作0来处理。

而对于非数值进行位操作,会先用Number()对其转换后再进行相应操作

  • 按位非 ~

其操作很简单,就是将二进制的数每一位都取反,0变1,1变0,底层实现感兴趣的盆友可以自行了解。

对于咱们前端来说,不一定需要知道底层的实现,但应该知道对一个值进行操作后会有怎样的影响。

对一个数进行~操作实际上就是将该数值变为负值然后减一

  • 按位与 &

有的朋友可能没用过&,但大多数感兴趣点进来的朋友应该都用过&&

&其实就是对数值的二进制的每一位都是用&&,这个操作需要两个操作数

就将两个数的二进制对齐后对每一位进行&&,如果两个数的对应位都为1那么这一位的值为1,其他情况这一位的值都为0

比如4&5

100

101

->100

所以结果为4

  • 按位或 |

其操作与上面的&很像,都需要两个操作数,不过不同的地方在于,两个数的二进制位上只要有一个是1就为1

即只有同时为0值才为0

同样用4和5举例

4|5

100

101

->101

所以结果为5

  • 按位异或 ^

异或顾名思义,即这一位上的数不同即相异即为真也就是1

这一位上的两个数相同(同为1或同为0)这一位的值为0

说白了,也就是判断这一位上的两个二进制数是否相同,相同为0,不同为1

同样以4、5举例

4 ^ 5

100

101

->001

即值为1,

  • 左移

<< 两个小于号表示将一个数的二进制数向左移

a<<b 即表示将 a 向左移 b 位

左移后的空位以0填充

实际上也就是将 a 乘 2的b次方

以4、5举例

100 向左移动 5 位 变成:

10000000 -> 128 也就是 4 * 32 或者 4 * 2^5

  • 右移

跟左移相反,右移一位即除以2;

相当于将2进制的最后一位抹去,结果也就是整除2的结果

4 >> 2

100 -> 1

需要注意的是与左移不同右移产生的空位会以符号位来填充

比如-5 >> 2

在32位2进制中:

5: 0000 0000 0000 0000 0000 0000 0000 0101

转为-4(以补码的形式保存)

-5:  1111 1111 1111 1111 1111 1111 1111 1010

右移2位:

1001 1111 1111 1111 1111 1111 1111 1110

空位以符号位补齐(这里的值是补码,求原来的值需要-1再按位取反)

1111 1111 1111 1111 1111 1111 1111 1110

1111 1111 1111 1111 1111 1111 1111 1101

1000 0000 0000 0000 0000 0000 0000 0010

即得到的结果为

-2

  • 无符号右移 >>>

与一般的右移不同。无符号右移不会以符号为来填充空位

而是用0来填充,并且符号位也会随之右移,所以对正数来说并不会有什么不同

而对于负数就有所区别了

以刚才-5的例子为例如果是无符号右移:

-5:1000 0000 0000 0000 0000 0000 0000 0101

补码: 1111 1111 1111 1111 1111 1111 1111 1011

右移2位:0011 1111 1111 1111 1111 1111 1111 1110

由于符号位是0,所以会当成一个正数

所以答案为2^30-2

也就是

位运算操作符就介绍到这里

下面介绍布尔操作符

布尔操作符

  • 逻辑非!

返回一个boolean值

其规则为将一个操作数先用boolean()转换为布尔值

然后再对求到的值进行求反操作

即true->false  false->true

至于Boolean()的转换规则在之前的文章中已经介绍,这里不再赘述

甚至要是你愿意可以用 !! 来代替Boolean()

你会得到一致的结果

  • 逻辑与 &&

该操作符需要两个操作数,只有当两个操作数都为真时,返回的值才为真(true)

需要注意的地方在于,如果两个操作数中有一个不是布尔类型的值,那么返回值就不一定是布尔类型

遵守如下规则:

第一个操作数为对象,则返回第二个操作数

如果第二个操作数为对象,则只有第一个操作数的求值结果为true才会返回该对象

两个操作数都是对象那么返回后面那个

第一个为null 返回 null

第一个为undefined 返回 undefined

第一个为NaN返回NaN

书上的这段话可能有一些难以理解,我来稍微翻译一下吧

当两个操作数都为布尔类型时会返回一个布尔类型的值,规则和按位与的意思一样这里不再多说。主要的在于下面的部分

实际上,我们用的更多的是非布尔值,使用&&来做流程控制,&&实际上是一种短路操作。

我们知道,对于与运算必须两个值都为1结果才为1,也就是说只要一个值为0,那么结果肯定为0

所以可以这样理解&&会先将非布尔的值使用Boolean()转换成布尔值进行判断,如果值为false那么就将当前的非Boolean值返回,如果为true就判断下一个,如果都为true那么返回最后的那个非布尔值

  • 逻辑或 ||

跟逻辑与相反,逻辑或一遇到真值就会停止,不会继续往后判断

所以我们在做浏览器兼容的时候往往就会使用 || 来做浏览器的功能性检测

这里的例子也和上面的差不多,所以就不贴出来了,因为这两个布尔操作符更重要是使用场景。

做前端的应该都知道对于样式,有优雅降级,和渐进增强的说法

其实我觉得这两种操作符的适用场景和,上面的两种说法有点像;

&&相当于就是渐进增强,因为如果你第一个满足条件,第二个也满足条件取后面的那个。

这就像是有几个对象同时满足条件,只要我们把更好的放在后面,就可以让程序运行时,自动选择更好的对象作为其他用途。

常见场景是封装函数的内部,可能有些参数可以覆盖其他的参数,内部就可以使用&&来完成

而||呢就像是优雅降级,取一个能满足条件的就不继续向后判断了(这里的形容可能不太恰当)

所以更加适用于做浏览器兼容的场景,只要最新的特征能够满足。我就没有必要去检测老版本的DOM API了

乘性操作符

ECMA中定义了3种乘性操作符

乘法、除法、求模

这些操作和其他语言中的很像,唯一不同的是JS在运算前会使用Number()进行转换

乘法:

其用法和原理相信大家应该都知道

我就补充一下对于特殊值的处理:

1.如果有一个操作数是NaN那么结果就是NaN

2.无穷与0相乘结果为NaN

3.无穷与非0相乘得到正负无穷

4.无穷与无穷相乘结果为无穷

除法:

特殊规则如下:

求模

也就是我们常说的取余数

需要注意的也就是一些特殊规则:

加性操作符

加性操作符很简单,即加减运算

特殊规则:

对于+:

只要有一个操作数是字符串,那么+的操作就会变为字符串的拼接(不是字符串的转为字符串后操作)

加减都适用:

一个操作数为NaN那么结果为NaN(优先级次于+)

对于无穷,只有正无穷和负无穷相遇才会为NaN(因为都超出了范围所以没法计算)

而两个正无穷或两个负无穷就是符合逻辑的值

也就是 两个正的无穷大 加到一起当然还是正无穷

两个负无穷相减当然还是负无穷

关系操作符

即大于 > 小于 <  大于等于 >=  小于等于 <=

规则如下:

一个操作数为NaN则返回false

都是字符串比较字符串的编码值

布尔转为数值进行比较

对对象使用Number()后进行比较

有一个操作数为数值,将另一个转为数值后进行比较

PS:Js中是存在既不小于1也不大于等于1的值的(手动滑稽),那就是NaN,因为怎么比较都会返回false

相等操作符

相等== 不相等!=

上面两种操作符会转换数据类型后进行比较

规则如下:

与关系操作符相似,都是进行数值的比较

boolean会转为数值后进行比较

一个是对象另一个不是,则会调用对象的valueOf后进行比较

一个数值另一个是字符串,将字符串转为数值后比较

null和undefined相等

一个操作数是NaN相等操作返回false,不等返回true(即所有值和NaN都不相等包括它本身)

两个都是对象则比较是否为同一对象

全等=== 不全等!==

不会转换类型,直接进行比较

规则类似于相等

不过除了判断值之外还会判断类型是否相等

即 undefined !== null

条件操作符

表达式?值1:值2;(三目运算符)

对表达式求值,值为true返回值1,值为false返回值2

赋值操作符

=

将右侧的值赋值给左侧的变量

PS *= += 等复合赋值操作符只是简化了操作,但不会带来性能上的提升

逗号操作符

用于在一条语句中执行多个操作

如声明变量

或者:

var a = (1,2,3,4,5); // 5

以上就是今天的内容了,感谢浏览,求赞 ^_^

Javascript高级编程学习笔记(5)—— JS操作符的更多相关文章

  1. Javascript高级编程学习笔记(3)—— JS中的数据类型(1)

    前一段时间由于事情比较多,所以笔记耽搁了一段时间,从这一篇开始我会尽快写完这个系列. 文章中有什么不足之处,还望各位大佬指出. JS中的数据类型 上一篇中我写了有关JS引入的Script标签相关的东西 ...

  2. Javascript高级编程学习笔记(1)—— JS简介

    此系列文章,用于记录所学,如有错误欢迎指出. Javascript组成 1.核心(ECMAScript) 2.文档对象模型(DOM) 3.浏览器对象模型(BOM) 1.核心(ECMAScript) E ...

  3. Javascript高级编程学习笔记(4)—— JS中的数据类型(2)

    接着昨天的文章,今天这篇文章主要讲述JS中剩余的两种数据类型String,和Object String类型 对于该类型,书中给出的解释为:由0或多个16为Unicode字符组成的字符序列. 对于JS中 ...

  4. JavaScript高级编程学习笔记(第三章之一)

    继续记笔记,JavaScript越来越有意思了. 继续... 第三章:JavaScript基础 ECMAScript语法在很大程度上借鉴了C和其它类似于C的语言,比如Java和Perl. 大小写敏感: ...

  5. Javascript高级编程学习笔记(25)—— 函数表达式(3)模仿块级作用域

    昨天写了闭包 今天就来聊聊块级作用域的事情 在绝大多数编程语言中,都有块级作用域这个概念 什么是块级作用域呢? 前面我们在刚开始讲的时候说过,JS中的大括号(不在赋值运算符的后面)表示代码块 块级作用 ...

  6. Javascript高级编程学习笔记(8)—— 变量

    日常更新~~ 变量 所有的编程语言中,变量都是赋予语言灵活性的根本所在. 那么JS中的变量又有那些与众不同的地方呢.? 按照ECMA-262的定义,JS的变量和其他编程语言的变量有很大的区别 其松散类 ...

  7. Javascript高级编程学习笔记(6)—— 流程控制语句

    话不多说,我们直接开始进入今天的主题 流程控制语句 首先什么是流程控制语句呢? 顾名思义,就是控制流程的语句. 在JS中语句定义了ECMAScript中的主要语法,让我们可以使用一系列的关键字来完成指 ...

  8. Javascript高级编程学习笔记(97)—— WebGL(3) WebGL上下文(1)

    WebGL上下文 在支持WebGL的浏览器中,WebGL的名字为 "experimental-webgl",这是由于 webgl 的规范仍未制定完成 制定完成后名字就会改为简单的 ...

  9. Javascript高级编程学习笔记(57)—— 事件(1)事件流

    事件 JS与HTML的交互是通过事件实现的 而事件指的就是:文档或浏览器窗口特定的交互瞬间 可以通过侦听器来预定事件,以便在事件发生时执行相应的代码 这种模式也是设计模式中的观察者模式 事件流 有了事 ...

随机推荐

  1. 记号一次更换IBM X3650M4主板后RAID无法启动的解决

    https://wenku.baidu.com/view/9d503ef367ec102de2bd89d7.html 强烈感谢上面分享文档的大侠!! 1.更换主板后,linux系统,无法加载引导.需要 ...

  2. centos安装tree命令

    centos安装tree命令 sudo yum -y install tree windows安装tree命令 我的另一篇

  3. R语言-箱型图&热力图

    1.箱型图 boxplot()函数 > metals<-read.csv("metals.csv",header=TRUE) #读取文件和列名 > boxplot ...

  4. 《CSAPP》地址翻译

    本节所使用的符号: 地址翻译 地址翻译是一个N元素的虚拟地址空间(VAS)中的元素和一个M元素的物理地址空间(PAS)中元素之间的映射. 映射实现: MMU利用页表来实现这种映射.CPU中的一个控制寄 ...

  5. python下划线的5种含义

    本文介绍了Python中单下划线和双下划线("dunder")的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类. 单下划 ...

  6. 初学c# -- 学习笔记(9) 关于SQL2008

    在做一个局域网的类似网盘的学习练习,服务端差不多了,在改bug.用vlc的dll做的全格式视频.音频预览在线播放下载等等. 在做服务端也遇到了一些问题,走了好多弯路. 开始把上传的视频.音频.图像.文 ...

  7. as3.0 当fla里面有TLF文本的时候,加载声音会出现错误

    问题描述 1.现有制作好的mp3加载包,这个包是相对路径 2.如果fla里面没有TLF文本,可以正常运行 解题思路 1.音频的相对路径和加载TLF文本的路径不一样,fla会优先选择TLF文件,这样mp ...

  8. Curl 基本命令

    下载单个文件,默认将输出打印到标准输出中(STDOUT)中 curl http://www.centos.org 通过-o/-O选项保存下载的文件到指定的文件中:-o:将文件保存为命令行中指定的文件名 ...

  9. 100-days: sixteen

    Title: The world's most expensive cities 生活成本最高的城市 For the first time in its 30-year history, the Wo ...

  10. [leetcode]51. N-QueensN皇后

    The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens ...