首先我们要学好一个东西, 那么就要知道他底层是怎么运行的
比如说 我们用对象转数字
1.先去看我们的对向上有没有Symbol.toPrimitive方法,如果有这个方法就先执行这个方法
2.如果没有Symbol.toPrimitive属性,那么就执行valueOf 方法,获取它的原始值
3.然后再执行 toString 方法把他变成字符串
比如说
接下来我们看一到 很金典的面试题
let a = ?;
if(a == 1 & a==2 & a == 3) {
console.log("ok");
}
很明显 这个是考察我们的隐式转化的问题,对象转数字
== 会存在隐式转化,转化成相同类型的值去比较, === 则不会隐式转化,
所以写代码 最好是写 ===
答案如下
// 方案一
let a = {
i: 0,
[Symbol.toPrimitive] () {
return ++this.i;
}
};
// 方案二
let a = [1,2,3];
a.toString = a.shift;
这样子 同样也可以打印出ok, shift是每次拿到第一个值,并返回这个数字
//方案三 通过数据劫持的方法
var i = 0;
Object.defineProperty(window, "a", {
get() {
return ++i;
}
})
// 只要这里一用到a 就会被截取, 然会做返回处理
if(a == 1 & a==2 & a == 3) {
console.log("ok");
}
// 方案四 我们学过Vue3.0 就知道 响应式是通过 Proxy 去做的拦截,所以说可以通过Proxy去做 方法也跟上面方案三差不多
这个样子写 答案就是可以打印出ok了, 我们前面也说了 顺序是
Symbol.toPrimitive -> valueOf -> toString 你重写这三个方法中哪一个都可以
说到这里了 我就简单的提一下 +
+有两个作用
1.字符串拼接
只要是左边跟右边其中有一个是字符串,那么就是字符串拼接
比如:
const result = 10 + 12.5 + "a" + [] + 10 + 30;
//解释: 10跟12.5 都是数字,所以变成了22.5 然后再加上a 就变成了字符串, []转字符串就是""
答案是 '22.5a1030'
2.隐式转化成数字
+new Date()
Date 就有这个属性 Symbol.toPrimitive
结果就是时间搓
我们来看一下 parseInt的用法
parseInt(value, redix)
第一个参数是值,必须是字符串,不然可能出现其他的问题
第二个是进制, 返回值 2进制到36进制
第二个参数不写,默认是10进制
parseInt("013") // 13
parseInt("01554sdfs") // 1554
parseInt(013) // 11
parseInt(“01554sdfs”) 为什么是 1554, 原理是他会一个一个的去找,
0 1 5 5 4 遇到s了 判断是不规则数字,那么就不会再继续往下走了,那么就会把
前面的 01554 做10进制的转换 就变成了 1554
为什么会出现上面的这个结果, 如果第一个参数是数字不是字符串, 并且是以 0 开头的话就会默认以8进制来处理, 所以结果是 11
那我们来看下面这到面试题
let arr = [27.2, 0, "0013", "14px", 123];
arr = arr.map(parseInt);
console.log(arr);
结果是这个, 卧槽, 怎么是这些值, 是不是头都大了
下面来给你解释为什么
map是要执行完成了,并且会把最新的那个值给覆盖原来的值,返回一个新的数组
arr.map(parseInt);
其实就是
arr.map((item, index) => {
return parseInt(item, index)
});
那么第一项 如果parseInt第二项填的是0 那么他的作用跟10进制是一样的
parseInt(27.2, 0) // 结果是27
parseInt(0, 1) // 因为我们的进制范围是 2~36 所以1进制是不符合的 就返回了NaN
parseInt( "0013", 2) // 0 0 1 (3是不符合2进制的, 所以舍弃)001的2进制 结果是 1
parseInt( "14px", 3) // 同样 4也不满足三进制 就只有1 的三进制 结果就是1
parseInt( 123, 4) // 都满足 1*4^2 + 2*4^1 + 3*4^0 结果就是 16 + 8 + 3 = 27
上面就是这个题的答案
那我们老看一下,浮点型的问题
0.1 + 0.2 == 0.3 ?
答案是什么?
结果是 false? 为什么, 这个就是扯到我们浮点数 丢失精度的问题了0.1 + 0.2
请看下面这个图, 浮点数 存放的是2进制, 所以他会一直 *2 , 如果大于1了就放在左边,然后计算机是64位操作系统, 所以只会保存64个字节,然后多余循环的就省去了,这个就存在精度丢失的问题了
如果我们想解决 精度丢失的问题, 那么就把他先扩大变成 整数, 然后再除以放大的倍数就得到我们的结果了
// 这个是 得到放大多少的倍数
const pow = function pow(target) {
const [, result] = target.split(target);
return Math.pow(10, result.length)
}
const plus = function plus(val1, val2) {
val1 +="";
val2 +="";
if(isNaN(val1) || isNaN(val2)) return NaN;
// 这个是为了拿到最大的那个商职
let max = Math.max(pow(val1), pow(val2));
return (val1 * max + val2 * max) / max;
}
console.log(plus(0.51, 0.2546));