「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
一、数值的扩展
1.1 进制转换问题
首先,我们想一想,在ES5中我们如何将十进制转换为二进制呢?大家肯定都想到了toString。我们可以实现一下。
const a = 5
console.log(a.toString(2)) //101
那么,有如何将二进制转换为十进制呢?我们可以用parseInt来解决这一问题。下面得代码的意思就是将a这个变量看做二进制去进行转换。
const a = 101
console.log(parseInt(a,2)) //5
在ES6中,新增了两种方法为我们表示二进制和八进制数。分别是0B和0O。
const a = 0B0101
console.log(a) //5
const b = 0O666
console.log(b); //438
1.2 经典面试题 0.1+0.2 === 0.3 ?
这道题是经典的面试问题。我想大家肯定经常遇到。但是你有没有想过其中的原理呢?首先,从数学角度来看,答案是肯定的,肯定是正确的。但是在计算机中,答案却是false。要了解其中的原因,首先我们要知道计算机当中数字是如何存储和运算的。
在计算机中数字按照IEEE 754(双精度标准)来存储,我们可以简单粗暴地理解为二进制存储的位数比较多就可以。重点是位数比较多。比如我们用八位二进制数存储35这个数字。
35->00100011
0.375->0.011
但是当我们存储0.1时 我们发现是永远除不尽的(首先你要知道是小数转换为二进制运算方式)
0.1-> 0.000110011......
因为计算机存储位数是有限的,所以,计算机会舍弃后面的部分。所以我们得到的是一个近似值。0.1后面最多还可以有15位
console.log(0.1000000000000001) //0.1000000000000001
console.log(0.10000000000000001) //0.1
所以,0.1+0.2===0.3在计算机中是false.因为精度缺失问题。
1.3 Number.isFinite
Number.isFinite()用来检测指定参数是否无穷大。
console.log(Number.isFinite(1234)) //true
console.log(Number.isFinite(NaN)) //false
console.log(Number.isFinite(Infinity)) //false
console.log(Number.isFinite(-Infinity)) //false
console.log(Number.isFinite(null)) //false
console.log(Number.isFinite(0)) //true
console.log(Number.isFinite('0')) //false
它与window下的isFinite()的区别是 不会将检测值转换为Number。
1.4 Number.isNaN()
Number.isNaN()确认传入的参数是否为NaN(not a number)。也就是说判断传入的参数是不是为一个不是number类型的标识符。
console.log(Number.isNaN(0)) //false
console.log(Number.isNaN('0')) //false
console.log(Number.isNaN(NaN)) //true
console.log(Number.isNaN(null)) //fasle
window.isNaN与Number.isNaN()的区别:
Number.isNaN()不会将值转换为Number,并且对于任何非Number类型的值也不会返回true。
1.5 Number.parseInt()和Number.parseFloat()
Number.parseInt()将参数按照有符号的十进制整数进行解析,他的第二个参数表示转换参数想要的进制。
Number.parseFloat()也是从第一个字符(位置0)开始解析每一个字符。也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。他没有第二个参数。
1.6 Number.IsInteger()
Number.IsInteger()判定传入的参数是否是整数
console.log(Number.isInteger(0)); //true
console.log(Number.isInteger(1)); //true
console.log(Number.isInteger(-1)); //true
console.log(Number.isInteger(null)); //fasle
console.log(Number.isInteger(false)); //fasle
console.log(Number.isInteger(Infinity)); //fasle
1.7 Number.MAX_SAFE_INTEGER()与Number.MIN_SAFE_INTEGER()与Number.isSafeInteger()
Number.MAX_SAFE_INTEGER 常量表示在 JavaScript 中最大的安全整数(maxinum safe integer)(2^53 - 1)。
Number.MIN_SAFE_INTEGER 代表在 JavaScript中最小的安全的integer型数字 (-(2^53 - 1))。
Number.isSafeInteger() 判断传入的参数是否是一个安全的整数。
安全整数范围为 -(2^53 - 1)到 2^53 - 1 之间的整数,包含 -(2^53 - 1)和 2^53 - 1。
二、Math新增的方法
2.1 Math.trunc()
Math.trunc()会将数字的小数部分去掉,只保留整数部分。会把参数的类型转化为Number
console.log(Math.trunc(0.9)); //0
console.log(Math.trunc(2.6)); //2
console.log(Math.trunc(null)); //0
console.log(Math.trunc(false));// 0
2.2 Math.sign()
Math.sign()判断传入的参数是整数还是负数 或者0 或者NaN。会把传入的参数转换为Number。转换不了的就返回NaN。正数都返回1.负数返回-1. 0返回0
console.log(Math.sign(-1)); //-1
console.log(Math.sign(-2)); //-1
console.log(Math.sign(0)); //0
console.log(Math.sign(1)); //1
console.log(Math.sign(2)); //1
console.log(Math.sign(NaN)); //NaN
console.log(Math.sign(null));//0
console.log(Math.sign(false));//0
2.3 Math.cbrt()
Math.cbrt() 求一个数的立方根
Math.cbrt(NaN); // NaN
Math.cbrt(-1); // -1
Math.cbrt(-0); // -0
Math.cbrt(-Infinity); // -Infinity
Math.cbrt(0); // 0
Math.cbrt(1); // 1
Math.cbrt(Infinity); // Infinity
Math.cbrt(null); // 0
Math.cbrt(2); // 1.2599210498948734
三、反射Reflect
Reflect主要有四个作用:
- 将Object上的一些方法转移到Refelect上
- 修改某些Object方法返回的结果,让其变得更合理
- 让Object操作变成函数操作
- Reflect的方法和Proxy的方法一一对应
3.1 将Object上的一些方法转移到Refelect上
为什么这样设计呢?
随着ES的不断更新升级,Object下的一些方法设计并不合理。所以逐渐的将一些方法放在Reflect下面。也许有一天,某些方法在Object下,就可能移除,使用的时候需要使用Reflect下调用。这样做的好处是ES的代码可以更加规范,合理。
let obj = {}
let newVal = ''
Object.defineProperty(obj,'name', {
get() {
return newVal
},
set(val) {
newVal = val
}
})
obj.name = 'hello'
console.log(obj.name); //hello
上面的代码中的Object完全可以用Reflect代替
et obj = {}
let newVal = ''
Reflect.defineProperty(obj,'name', {
get() {
return newVal
},
set(val) {
newVal = val
}
})
obj.name = 'hello'
console.log(obj.name); //hello
3.2 修改某些Object方法返回的结果,让其变得更合理
比如说我们在用Object.defineProperty()去定义一些属性的时候,某些属性无法定义,我们需要用如下方法,抛出异常
try {
Object.defineProperty()
}catch {
//异常
}
但是,当我们使用Reflect时,会变得更加自然合理。避免使用try/catch,让代码更容易维护Reflect.defineProperty()会直接返回一个布尔值。
if(Reflect.defineProperty()) { //返回布尔值
}else {
}
3.3 让Object操作变成函数操作
我们之前查看Object下是否包含某个方法进行如下这种命令式操作。Reflect赋予了我们进行函数式操作的方式
console.log('defineProperty' in Object) //true 命令式操作
console.log(Reflect.has(Object,'defineProperty'))//true 函数式操作
3.4 Reflect的方法和Proxy的方法一一对应
et user = {
name: '张三',
age: 28
}
user = new Proxy(user,{
get(target,prop) {
return target[prop]
}
})
console.log(user.name); //张三
上述代码也可以用Reflect来改造,
let user = {
name: '张三',
age: 28
}
user = new Proxy(user,{
get(target,prop) {
return Reflect.get(target,prop)
}
})
console.log(user.name); //张三