基本小知识
* ==相等 ===绝对相等
* ==在比较的时候,如果两边类型不一致,则转换为相同的数据类型
* *** caniuse网站用来检测兼容性:
* NaN==NaN false Object.is(NaN,NaN)->true
* null==undefined -> true null===undefined -> false null&undefined和其他任何值比较都是不相等的
* 对象==字符串 对象转换为字符串
* 剩余的情况都是转换为数字
*
* ===类型不一致,不会转换,直接false
一、对象转换为数字/字符串「字符串拼接、数学运算、特殊方法处理、==比较(隐式转换、显式转换)
// *********下面这段话很重要:
// + 首先检测对象的 Symbol.toPrimitive 这个属性,获取其原始值 // + 如果没有这个属性,则继续调用它的valueOf,也是获取原始值 // + 如果值不是原始值,则继续调用toString转换为字符串 // + 再把字符串基于Number转换为数字
let obj = {
name: 'xxx'
};
console.log(obj - 10); //数学运算:先把obj隐式转换为数字,再进行运算 */
let obj = {
name: 'xxx',
[Symbol.toPrimitive](hint) {
// hint检测到浏览器隐式规定的转换类型:'number'/'string'/'default'
return 10;
}
};
console.log(obj - 10);
练习题:让下面的代码成立
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
第一类方案:隐式进行数据类型转换的时候进行处理的
1、重写[Symbol.toPrimitive]
var a = {
i: 0,
//[Symbol.toPrimitive]这个值也可以变为toString和valueOf
[Symbol.toPrimitive]() {
return ++this.i;
}
};
2、相当于重写toSting()方法
var a = [1, 2, 3];
// a.shift() -->1
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
第二类:ES6 数据劫持
let obj = {};
Object.defineProperty(obj, 'name', {
// 以后当我们操作对象的name属性的时候(获取或者设置),触发getter/setter
get() {
return '逗你玩';
},
set(value) {
console.log(value);
}
});
// var a = 12; //全局上下文中,基于var/function声明变量,也相当于给window设置了属性 window.a=12
var i = 0;
Object.defineProperty(window, 'a', {
get() {
return ++i;
}
});
if (a == 1 && a == 2 && a == 3) {
console.log('OK');
}
二、其它的数据类型转换为number类型
例如:==比较、数学运算(+不仅仅是数学运算,还有字符串拼接)
1、显式转换方案:
Number([val]) -> 隐式转换一般调取的都是这个方法「浏览器有自己的特殊处理,针对于每一种情况都有详细的规则」
2、parseInt 和Number区别
parsetInt/parseFloat([val])
parsetInt([val],[radix])处理机制:
(1)[val] 必须是一个字符串,如果不是,则也要默认转换为字符串
(2)[radix]不设置(或者写的是零):正常都是按照10处理的,如果字符串是以”0x“开始的,默认值是16...
(3)先在[val]中,找到所有符合[radix]进制的内容(从左到右查找,直到遇到不符合的为止「不论后面是否还有符合进制的,都不在查找了」),然后再把找到的内容看做[radix]进制,转换为十进制
(4)[radix]范围 2~36,除了0以外(0->10/16),不在这个范围内,结果都是NaN
3、练习
parseInt('12px') -> parseInt('12px',10) -> 在字符串中找到所有符合10进制的内容 ‘12’ -> 最后把'12'当做看做10进制,转换为10进制 -> 12
parseInt('12px',1) -> NaN //[radix]范围 2~36,除了0以外(0->10/16),不在这个范围内,结果都是NaN
console.log(parseInt(null)); //->parseInt('null',10) -> NaN
// 把其它进制转换为10进制?
// '10101' 2机制 -> 10进制
// 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 + 1*2^4
4、继续练习
把一个函数作为值传递给另外一个函数执行(实参):回调函数
1、parseInt(27.2,0)
==> parseInt('27.2') -> 27
2、parseInt(0,1)
==> NaN 进制从2-36 其余的全是NaN
3、parseInt('0013',2)
'001' 看做2进制 转换为10进制
1*2^0 -> 1
4、parseInt('14px',3)
'1' 看做3进制 转换为10进制
1*3^0 -> 1
5、parseInt(123,4)
parseInt('123',4)
'123' 看做4进制 转换为10进制
3*4^0 + 2*4^1 + 1*4^2 -> 3+8+16 -> 27
6、最好看一下map的源码
三、把其他的类型转换成布尔
* 把其它数据类型转换为布尔:
* 只有”0/NaN/null/undefined/空字符串“ 转换为false,其余都是true
* 例如:
* if(1){}
* ! 取反
* !! 转换为布尔
四、“+”
1、 ”+“作为字符串拼接
* 两边都有值,有一边出现字符串或者对象,则为字符拼接
* 特殊:{}+10 -> 10 {}看做代码块(ES6 块级上下文),真正运算的只有 +10 ->10
* ({}+10) -> '[object Object]10'
2、 +只有一边或者++x再或者x++,都是数学运算
10+(++x) -> 先把x累加1,然后和10运算
10+(x++) -> 先拿x的值和10运算,最后再x累加1
3、练习题
let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;
console.log(result);
// 10+{} -> "10[object Object]" 原本是想把{}变为数字,但是Symbol.toPrimitive/valueOf/toString,调到toString变为字符串,此时符合了有一边变为字符串了,则是字符串拼接
let x = '10';
console.log(++x); //->11
x = '10';
x += 1; //->x=x+1
console.log(x); //->'101'