运算符

235 阅读7分钟

本文介绍了JS中的运算符种类以及个别运算符作用和应用场景,前提需要你熟悉基本数据类型,了解隐式转换规则。

数据类型相关知识 JS-数据类型

隐式转换相关知识 JS-隐式转换

前置知识

  • 基本数据类型:StringNumberBooleanNullUndefinedSymbolBigint

  • 引用数据类型:ObjectArray Function DateRegExp

  • 转换规则

    • 其他转Numberboolean转为0/1,undefined转为NaNnull转为0,string调用Number(),symbol不支持

    • 其他转String:加“”;number直接转

    • 其他转Booleannull undefined +0 -0 “” NaN转为false,其他都是true

    • 引用类型转基本类型

      ToPrimitive(obj,type),一般type默认number,若obj是Date,type默认string。如果type是number,先调valueOf(),如果type是string,先调toString。ToPrimitive()一定会返回一个基本数据类型。

算数运算符

+-*/%**++--

+

  • 两个作用

拼接、相加;相加涉及隐式转换。

  • 两种类型

一元运算符、二元运算符,一元运算符优先级高。+'2' + +'3'=5

  • 三种情景A+B

    • 都是String直接拼接。
    • 一个是String,将非String转为String再拼接。
    • 都不是String,转为Number再相加。
  • 计算机怎么相加的?0.1+0.2!==0.3

    • 十进制转二进制:0.1和0.2都是1100循环
    • js双精度保留53位,多余会舍去
    • (a+b).toFixed(2)

-、 *、 /、 %、 ++、 --

  • 操作数值超过数值表示范围,结果为Infinity 或 - Infinity。
  • 操作数为NAN或Undefined,结果为NAN。
  • 操作数不是Number类型,先调Number()转换,再运算。
  • 操作数为对象,先对对象进行隐式转换,再运算。

逻辑运算符

&&、||

  1. &&|| 先对第一个操作数执行条件判断,若不是Boolean类型,就强制转换为Boolean类型,然后执行条件判断。
  2. &&||返回的是其中一个操作数的值,不是条件判断结果,其实就是对两边的布尔值进行逻辑运算。交集和并集的关系。
  3. A||B:假设A是true,B是false,其实就是1||0,若第一个操作数为true返回第一个操作数的值,反之,第一个操作数为false,返回第二个操作数的值。总之,都假才假。
  4. A&&B:假设A是true,B是false,其实就是1&&0,若第一个操作数为true返回第二个操作数的值;反之第一个操作数为false,返回第一个操作数的值。假设A是对象,返回B,假设B是对象则要保证A是true才能返回B。假设A B都是对象,返回B,总之,一假才假。

!

  • 操作数强制转为Boolean类型,取反。除了nullNaNundefined""0false,其都是true。

位运算符

&、 |、 ~

  • &:一假就假,都真才真、|:都假才假、~:按位取反

  • &可以判断一个数的奇偶性

a&1==1是奇数 a&1==0是偶数

除了最低位是2^0,其余都是2的整数倍,所以最低位决定数的奇偶性。 1的二进制:最低位是1,其余位都是0 。1*2^0=1

  • |取整、比较是否相等

a|0==a

a|b==a两数相等

  • ~取整

^

  • 相同为0,相异为1;a^0=a; a^a=0; 满足交换律、结合律

  • 应用:变量是数字,完成值交换,不加临时变量

    • a=a^b
    • b=b^a=b^a^b=a^b^b=a
    • a=a^b=a^b^a=a^a^b=b
  • 应用:查找数组中只出现一次的元素

    全部元素的异或运算结果即为数组中只出现一次的数字。a^a=0

<<、>>、>>>

  • <<左移若干位,丢高位,低位补0

  • >>右移若干位,丢低位,正数高位补0,负数高位补1

  • >>>无符号右移若干位,丢低位,高位补0,符号位永远是0,值永远是正数,对于非负数>>>>>结果相同。

比较运算符

==、=== 、!=、!==

  • ===值和数据类型都相同才行,也就是内存中存储的地址相同;==值相同就相同。

  • ==存在隐式转换会把两边数据类型转为一致,再比较值。

    1. 两边都是基本数据类型,若是null与undefined返回true,若是其他基本数据类型和number类型比较,则将其他基本数据类型转为Number。
    2. 有一个是引用数据类型,则将引用数据类型转为基本数据类型再比较。链接,怎么转?ToPrimitive(obj,type)
  • Object.is(a,b)===类似,但是NaN等于NaN,+0和-0不相等

  • null==undefined为true

  • null===undefined为false

  • NaN===NaN为false,NaN不等于任何值,包括它本身。

<、 <=、 >、 >=

  • 两个都是Number,进行数值比较,有一个不是Number就强制转为Number。
  • 两个都是String, 则比较两个字符串对应的ascii码。
  • 一个是Object,要先对其进行隐式转换,转为基本数据类型。

赋值运算符

=+=-=*=/=%=

基本数据类型赋值是栈中重新开辟一个存储空间,引用类型赋值的是栈中重新开辟一个存储空间,指向的堆内存空间的对应地址,指向堆中的地址是一样的

赋值的左操作数应该是一个引用记录,一个变量 var num = 10

引用两个操作:GetValue(V)对右边取值, PutValue(V,W)给左边设置值,第一个参数必须是引用

讲原理

条件运算符

条件?条件为真:条件为假

类型运算符

typeofinstanceof

其他运算符

.,()voiddeletein...

.

读取对象属性值,只能用在对象上,若点前面不是对象,先将其变为对象,调用完后再改回原来的类型。 通常用来判断this指向。

,

具备赋值操作GetValue(),返回第二个操作数。优先级比"="低。

()

(A)A可以是字面量或表达式,但是它不存在赋值操作,也就是不能不能用GetValue()取值 因为(delete aa)删除的是引用。

void

求表达式的值,或执行语句。 void值总是undefined。 a标签中return false阻止默认动作,与void(f())作用相同。

delete

  • 基础类型,delete删除的是操作表达式的结果,值 字面量 目标不存在则直接返回true。

  • 引用类型,删除的是引用。

  • 返回true

    • 删除对象属性或数组元素
    • 删除成功
    • 删除目标不存在
  • 返回false

    • 内置核心
    • 客户端属性
    • var 声明的变量,不能从全局或函数作用域删除
    • let const声明的变量,不能从声明的作用域删除
    • 不可枚举的属性 function 语句定义的函数
  • 删除原型属性

    delete Fn.prorotype.bar

in

a in b判断操作数a是否作为属性名存在于对象b中,是则返回true,不是则则返回false

...

扩展运算符 浅拷贝

综合案例

let name = "a"
const person = {
    name: "person.name",
    getName() {
        return this.name
    }
}
const getName = person.getName
console.log(getName())
console.log(person.getName())
console.log((person.getName)())
console.log((0,person.getName)())
  • 涉及运算符:=().
  • .运算符:读取对象属性值,只能用在对象上,若点前面不是对象,先变为对象,调用后再改回原来的类型。本质就是找this指向哪个对象,然后读取对象的属性或方法。this指向的是调用函数的对象
  • const getName = person.getName,若是引用类型,赋值操作会改变存储在内存中的地址。
  • getName()没有this,默认指向全局,读取全局作用域的name,但是let和const声明的变量不会放在全局对象上,所以是undefined。
  • person.getName()中this指向person,读取person里面的name。
  • (person.getName)()没有发生取值赋值操作,()有没有都一样,赋值才会改变地址也就是this指向。这里this指向person。
  • (0,person.getName)()中逗号是返回最后一个操作数据的值,产生赋值操作。优先级低于=,this指向全局对象,结果是undefined。

运算符测验

  • Infinity除、减Infinity、乘0都是NaN

Infinity * 0 = NaN

Infinity * null = NaN

Infinity * undefined = NaN

Infinity / undefined = NaN

Infinity / Infinity = NaN

任何数 % undefined = NaN

任何数 % NaN = NaN

Infinity % 任何数 = NaN

有限大的数 % 0 = NaN

Infinity - Infinity = NaN

(-Infinity) - (-Infinity) = -NaN

  • Infinity加减任何有限值都是Infinity

  • -Infinity加减任何值有限值都是-Infinity

  • 有限大的数 % Infinity = 有限大的数

Infinity - (-Infinity) = Infinity

Infinity - null = Infinity

Infinity * Infinity = Infinity

Infinity / 0 = Infinity

Infinity / null = Infinity

有限大的数 % Infinity = 有限大的数

0 % 除null、undefined、NaN任何数 = 0

数组原始值是""

对象原始值是[object,object]

[]+[]=''

[]+{}="[object,object]"

{}+[]=0

注意 [] {}转成boolean都是true;转成number,[]是0,{}是NaN。