banner
NEWS LETTER

I Know JS 运算篇

Scroll down

Math方法

1
2
3
4
5
6
7
8
Math.abs() // 绝对值
Math.ceil() // 向上取整
Math.floor() // 向下取整
Math.round() // 四舍五入
Math.trunc() // 直接返回整数部分,不论正负
Math.min() // 返回参数中最小值
Math.max() // 返回参数中最大值
Math.random() // 返回[0,1)中随机数

==、!=

这两个操作符会先进行类型转换(强类型转换)

表达式 结果
NaN == 任何 false
NaN != 任何 true
undefined == null

=== 和!==

比较时不转换操作数,只有在不转换操作数的情况下相等才返回true

使用var声明的变量会被自动添加到最接近的上下文(在函数中就是函数的局部上下文)。如果变量未经声明就被初始化了,那么它会被自动添加到全局上下文。

~ 操作符 (否运算)

~ 表示按位非,将每一位反转,操作数转化为32位的有符号整型,超过32位的数字将丢弃其最高有效位,注意是32位

1
2
3
const a = 5;
console.log(a.toString(2)); // 0000000000000000000101
console.log(~a); // 输出-6,对应二进制为 1111111111111111111010

?? 和 ||

??操作符的作用和||类似,当左值为undefined或null值时返回右值,否则返回左值,和||的不同在于只对undefined和null有用,而||对所有表示false的值生效,如:

1
2
3
4
undefined ?? 1 //1
null ?? 2 //2
false ?? 3 //false
"" ?? 4 //""

相等性的判断

严格相等比较 ===

比值前不进行隐式转换。如果两个被比较的值具有不同的类型,这两个值是不相等的。否则,如果两个被比较的值类型相同,值也相同,并且都不是 number 类型时,两个值相等。最后,如果两个值都是 number 类型,当两个都不是 NaN,并且数值相同,或是两个值分别为 +0-0 时,两个值被认为是相等的。

宽松相等比较 ==

Object.is() 的同值相等

1
2
3
4
5
6
7
8
9
10
11
12
13
// 向 Nmuber 构造函数添加一个不可变的属性 NEGATIVE_ZERO
Object.defineProperty(Number, "NEGATIVE_ZERO", {
value: -0,
writable: false,
configurable: false,
enumerable: false,
});

function attemptMutation(v) {
Object.defineProperty(Number, "NEGATIVE_ZERO", {
value: v
});
}

同值相等决定了两个值在所有上下文中是否在功能上相同。这一情况会在尝试修改一个不可变属性时发生。当尝试更改不可变属性时,Object.defineProperty 会抛出异常,但如果没有请求实际更改,则不会执行任何操作。如果 v-0,则没有请求更改,也不会抛出错误。在内部,重新定义不可变属性时,使用同值相等将新指定的值与当前值进行比较。

语言内部期望一个值等于另一个时,几乎所有地方都使用Object.is()函数提供的同值相等。

零值相等

类似于同值相等,但 +0 和 -0 视为相等
零值相等不作为 JavaScript API 公开,但可以通过自定义代码实现:

1
2
3
4
5
6
7
function sameValueZero(x, y) {
if (typeof x === "number" && typeof y === "number") {
// x 和 y 相等(可能是 -0 和 0)或它们都是 NaN
return x === y || (x !== x && y !== y);
}
return x === y;
}

零值相等与严格相等的区别在于其将 NaN 视作是相等的,与同值相等的区别在于其将 -00 视作相等的。这使得它在搜索期间通常具有最实用的行为,特别是在与 NaN 一起使用时。它被用于 Array.prototype.includes()TypedArray.prototype.includes()MapSet 方法用来比较键的相等性。

js中的连等赋值

1
2
3
4
5
let a = {n:1};
let b = a; // 持有a,以回查
a.x = a = {n:2};
alert(a.x);// --> undefined
alert(b.x);// --> {n:2}

解释:

  1. 首先创建一个对象{n:1}a指向这个对象
  2. b指向a指向的对象,即{n: 1}
  3. 给a指向的对象增加属性x,让a指向新的对象{n: 2},在这里,.运算符优先级高于=,所以这里的a.x实际上是对象{n: 1}xa.x=a实际上是将对象{n: 1}新增加的x属性赋值
  4. a现在指向对象{n: 2}a.xundefined
  5. b现在指向对象{n:1, x: {n: 2}},所以b.x{n: 2}
其他文章