前几天刷牛客对if (new Boolean(false))console.log('true')
竟然能正常输出true感到惊讶,去看了红宝书才发现有Boolean对象和Boolean原始值的区别。
先明确一下原始值和引值的区别。
new创建的Boolean对象,是对object类的继承,除了继承object的一些方法之外,还重写了比如valueof(),stringof()等的方法,他们的返回值都是true,false。
但是当我在nodejs里面测试又发生了迷惑,不是要对象才有方法,为什么tt一个基本类型可以使用方法呢?
let tt = 1;
console.log(tt.valueOf()) //1
然后在这个网址里看到了答案,这里是基本类型number,实际上有五种声明方式:
//方式一:最常见的方式,通过数字字面量方式声明,得到的就是一个普通的字面变量
var num = 123;
//方式二:Number其实就是个函数,做类型的强制转换,如果有不合规的字符会直接失败返回NaN
var num = Number(123);
//方式三:很少使用,各神书都将其列入不推荐方式,返回的是对象,该对象能够访问Number的原型属性以及方法
var num = new Number(123);
console.log(typeof num); //输出:object
console.log(Object.prototype.toString.call(num)); //输出:[object Number]
//方式四:神方式,目前还没见过人使用,当参数为数字时本质和3一样
var num = new Object(123);
//方式五:更离奇,更诡异,本质也是3
var num = Object(123);
至于第一种原始值为什么可以调用方法,原作者解读犀牛书做出了这样的理解:
当用户通过字面量方式声明一个变量,并在该变量上调用如toString等方法,JS脚本引擎会偷偷地创建该变量对应的包装对象,并在该对象上调用对应的方法;当调用结束,则销毁该对象;这个过程对于用户来说是不可见的,因此不少初学者会有这方面的困惑。
这样就很清楚了。
哦还有个很奇怪的类型判断,就像+的时候有一边有字符串,另一边也会被强制转换成字符串一样,==
的两边会发生强制类型转换。
{}==0
不成立,但是[]==0
成立。这是因为==
的比较只能发生在原始类型,不是原始类型的都要现转换成原始类型,也就是valueof()或者toString()中能转换成原始类型那个和原始类型比较。因此valueof或者toStringof一般不是我们调用而是类型转换时自动调用的。
然后原始类型的比较全部都要被转换成Number类型。