JavaScript运算符

运算符,加减乘除一直都是语言的基础,和小学数据逻辑也很接近,可以说是简单的已经不能再简单了。但是在js中,总有让你打脸的地方

  1. 加法运算#
    (1)加法运算符<code>(+)</code>是最常见的运算符之一,但是使用规则却相对复杂。因为在JavaScript语言里面,这个运算符可以完成两种运算,既可以处理算术的<b>加法</b>,也可以用作字符串<b>连接</b>。

加法

1 + 1 // 2  没有对象或字符串, 数值相加
true + true // 2    Number(true)==1
1 + true // 2

字符串连接

'1' + '1' // "11"
'1.1' + '1.1' // "1.11.1"
 1.如果运算子是对象,先自动转成原始类型的值。

即先执行该对象的<code>valueOf</code>方法,如果结果还不是原始类型的值,再执行<code>toString</code>方法;如果对象是<code>Date</code>实例,则先执行<code>toString</code>方法

2.两个运算子都是原始类型的值以后,只要有一个运算子是字符串,则两个运算子都转为字符串,执行字符串连接运算。
3.否则,两个运算子都转为数值,执行加法运算。

'1' + {foo: 'bar'} // "1[object Object]" 对象调用toString之后字符串相加
'1' + 1 // "11"  第一个是字符串,则使用字符串拼接
'1' + true // "1true" 
'1' + [1] // "11"

上面代码中,由于运算符左边是一个字符串,导致右边的运算子都会先转为字符串,然后执行字符串连接运算。

这种由于参数不同,而改变自身行为的现象,叫做“重载”(overload)。由于加法运算符是运行时决定到底执行那种运算,使用的时候必须很小心。

'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"

相等于

(3+4) + '5'

加法运算符会将其他类型的值,自动转为字符串,然后再执行连接运算。

var x = 1;
x + '' // "1" 转字符串1

1, 2] + [3]  // 1,23

相等于

"1,2" + "3"  // 数组先转为对应的字符串再进行拼接

(2)加法运算符一定有左右两个运算子,如果只有右边一个运算子,就是另一个运算符,叫做“数值运算符”。

+ - 3 // 等同于 +(-3)
+ 1 + 2 // 等同于 +(1 + 2)
+ '1' // 1
1 +  //   SyntaxError: Unexpected end of input

<b>加法运算符以外的其他算术运算符(比如减法、除法和乘法),都不会发生重载。它们的规则是:所有运算子一律转为数值,再进行相应的数学运算。</b>

1 - '2' // -1
1 * '2' // 2
1 / '2' // 0.5
var now = new Date();
typeof (now + 1) // "string"
typeof (now - 1) // "number
  1. 余数运算符(%)#
    需要注意的是,运算结果的正负号由第一个运算子的正负号决定。
  -1 % 2 // -1
   1 % -2 // 1
  -1% -2 // -1负数对比自己小的数求余都是自身
  -1 % -1 // -0
  1. 比较运算符的算法#
    1.如果运算子是对象,先自动转成原始类型的值(即先执行该对象的valueOf方法,如果结果还不是原始类型的值,再执行toString方法)。
    2.如果两个运算子都是字符串,则按照字典顺序比较(实际上是比较Unicode码点)。
    3.否则,将两个运算子都转成数值,再进行比较。

     [2] > [1] // true
    

等同于 '2' > '1'

[2] > [11] // true

等同于 '2' > '11'

{x: 2} > {x: 1} // false

等同于 '[object Object]' > '[object Object]'

  1. 相等运算符和严格相等运算符#

(1)简单说,它们的区别是相等运算符<code>(==)</code>比较两个值是否相等,严格相等运算符<code>(===)</code>比较它们是否为“同一个值”。如果两个值不是同一类型,严格相等运算符<code>(===)</code>直接返回false,而相等运算符<code>(==)</code>会将它们转化成同一个类型,再用严格相等运算符进行比较。

/**类型不同,直接返回false*/
1 === "1" // false  
true === "true" // false 

/**类型相同且值相同*/
1 === 0x1 // true 注:typeof 0x1 === "number"

NaN === NaN // false Nan与任何值都不相等
+0 === -0 // true 除了作为分母,它俩性质一样

(2)两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。

{} === {} // false
[] === [] // false
(function (){} === function (){}) // false

var v1 = {};
var v2 = v1;
v1 === v2 // true

(3)<code>undefined</code>和<code>null</code>与自身严格相等,所以,判断两个参数时,还需谨慎。

undefined === undefined // true
null === null // true

var v1;
var v2;
v1 === v2 // true

(4)注意,对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。

new Date() > new Date() // false 值比较
new Date() < new Date() // false 值比较
new Date() === new Date() // false 地址比较
  1. 布尔值运算符#
    5.1概述
    布尔运算符用于将表达式转为布尔值,一共包含四个运算符。

取反运算符:!
且运算符:&
或运算符:||
三元运算符:?:
5.2 !运算符

对于非布尔值的数据,取反运算符会自动将其转为布尔值。规则是,以下六个值取反后为<code>true</code>,其他值取反后都为<code>false</code>(取反运算符有转换数据类型的作用)。

!undefined // true
!null      // true
!false     // true
!0         // true(包括+0和-0)
!NaN       // true
!''        // true

!54 // false
!'hello' // false
![] // false
!{} // false

!!x

等同于

Boolean(x)
5.3 且运算符
如果第一个运算子的布尔值为<code>true</code>,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为<code>false</code>,则直接返回第一个运算子的值,且不再对第二个运算子求值。

't' && '' // ""
't' && 'f' // "f"
't' && (1 + 2) // 3
'' && 'f' // ""
'' && '' // ""

var x = 1;
(1 - 1) && ( x += 1) // 0
x // 1

5.4 或运算符
如果第一个运算子的布尔值为<code>true</code>,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为false,则返回第二个运算子的值。

't' || '' // "t"
't' || 'f' // "t"
''  || 'f' // "f"
''  || ''  // ""
  1. 位运算符#
    6.1 概述
    或运算(or):符号为|,表示若两个二进制位都为0,则结果为0,否则为1(有1则1)。
    与运算(and):符号为&,表示若两个二进制位都为1,则结果为1,否则为0(11则1)。
    否运算(not):符号为~,表示对一个二进制位取反。
    异或运算(xor):符号为^,表示若两个二进制位不相同,则结果为1,否则为0。(同0异1)

位运算符直接处理每一个比特位(bit),所以是非常底层的运算,好处是速度极快,缺点是很不直观。位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。另外,虽然在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数。

转32为整数

function toInt32(x) { 
return x | 0;
}
toInt32(1.001) // 1
toInt32(1.999) // 1
toInt32(1) // 1
toInt32(-1) // -1

一个整数大于32位的数位都会被舍去

toInt32(Math.pow(2, 32) + 1) // 1
toInt32(Math.pow(2, 32) - 1) // -1

6.2 或和与

0 | 3 // 3
0 & 3 // 0

/**
*位运算只对整数有效,遇到小数时,会将小数部分舍去,只保留整数部分。
*所以,将一个小数与0进行或运算,等同于对该数去除小数部分,即取整数位
*不适用超过32位整数最大值2147483647的数
*/

2.9 | 0 // 2
-2.9 | 0 // -2
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,114评论 0 13
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    徵羽kid阅读 657评论 0 0
  • 运算符是处理数据的基本方法,用来从现有的值得到新的值。JavaScript 提供了多种运算符,本章逐一介绍这些运算...
    许先生__阅读 596评论 0 3
  • 运算符 JavaScript中运算符主要用于连接简单表达式,组成一个复杂的表达式。常见的有算数表达式、比较表达式、...
    阿鲁提尔阅读 281评论 0 1
  • 常看到一些有关富人与穷人的思维差异的文章与书籍,其中有一条自己印象深刻:穷人总是按照自己已有的资源去考虑做事情,而...
    杨梅泡酒阅读 173评论 0 1