在古代神话中,狮身人面像是巨人与蛇妖所生的怪物:人的头,狮子的躯体,带着翅膀,名叫斯芬克斯。斯芬克斯生性残暴,他从智慧女神缪斯那里学到了许多谜语,常常守在大路口。每一个行人要想通过,必须猜谜,猜错了,统统吃掉,难倒无数的人。
有一次,以为国王的儿子被斯芬克斯吃掉了,国王愤怒极了,发出悬赏:“谁能把他制服,就给他王位!”。勇敢的青年狄浦斯,应国王征召前去报仇。他走呀走呀,来到了斯芬克斯把守的路口。
“小伙子,猜出谜题才能让你通过” 斯芬克斯拿出最难最难的一道题给他猜。
“javascript的类型有两种,一种是基础类型,另一种是引用类型,这两种分别是?”
js的基础类型有undefined、null、Boolean、Number、String
js的引用类型有Object、Array、Function、Date、RegExp
聪明的狄浦斯很快就猜出来了,然而斯芬克斯却不服输,又给狄浦斯出了一道谜题:
“typeof的使用及其底层原理”
typeof 数值/NaN // 'number'typeof 字符串 // 'string'typeof true/false // 'boolean'typeof 函数 // 'function'typeof js内置对象 // 'object'typeof null // 'object'typeof undefined // 'undefined'typeof 未定义的变量 // undefined
typeof是直接根据值的二进制表示来判断其类型的
000 //对象1 //整数100 //字符串110 //布尔000000…. //null-2^30 //undefined因为null的二进制表示是全0,所以会被判断成object
如果对象中有了call方法,那么会被判断成function
typeof只能区分基本类型以及引用类型的Object、Function
Object.prototype.toString().call()
Object这个构造器的原型有toString方法,所有继承自Object的类( Array、String、Boolean、Function等)都会继承这个方法。 而这个方法会返回[object 调用该方法的变量的构造器的名字], 比如:
- Object.prototype.toString.call(1) // [object Number] 因为1会被js内置的Number构造器包装起来,所以返回[Object Number]
- Object.prototype.toString.call('1') // [object String] 同上String构造器
- Object.prototype.toString.call(true) // [object Boolean] 同上Boolean构造器
- Object.prototype.toString.call(Symbol()) // [object Symbol] 同上Symbol构造器
- Object.prototype.toString.call(foo) // [object Function] 同上Function构造器
- Object.prototype.toString.call([1,2,3]) // [object Array] 同上Array构造器
- Object.prototype.toString.call({}) // [object Object] 同上Object构造器
- Object.prototype.toString.call(undefined) // [object Undefined] 比较特殊 直接判断
- Object.prototype.toString.call(null); // [object Null] 比较特殊 直接判断
单绝大部分js的类都会重写toString方法,所以想要用最原始的toString功能,就得通过Object.prototype.toString.call()来改变this指向 该方法能清晰的判断所有的基本类行和引用类型
斯芬克斯大吃一惊,此人竟能回复的如此详细,待我再给他一道。
“二元操作符===和==分别是干什么的”
狄浦斯思考了片刻,回答道:
===是比较两个变量是否类型相同,并且值是否相同
1==='1' // false1===2 // false1===1 // true
==是放宽版的===,允许两个变量的类型不一致,会进行一定的类型转换
null == undefined // true 规定1 == '1' // true 一个数值、一个字符串,将字符串转数值,然后比较true == '1' // true 当有布尔类型时,true转1,false转0,然后去比较引用类型变量 == 基础类型变量 // 当两个变量的其中一个是引用类型,另一个是基础类型,则将引用类型转化为数值再进行比较其他类型的比较都返回false
斯芬克斯吐了一口老血,嘴上骂道:“你tm是犀牛书转世吧!”
“这是我最后的波纹了,你要答对,我就去世”
“引用类型这么多,他们是如何转化成基础类型变量的”
“哼”,狄浦斯嘴角一歪,摆出一个标准的龙王不屑√
引用类型转基础类型主要就是转成Number和String
`当一个引用类型需要转成string类型时`\
`如果引用类型有toString()方法,且toString()返回的是基础类型,则将其转成字符串,再返回`\
`否则,如果引用类型没有toString()方法,或者toString()返回的不是一个基础类型,则调用valueOf()`
比如
{x:1,y:2}.toString() // [object Object][1,2,3].toString() // '1,2,3'function(x) { f(x) }.toString() // function(x) {\nf(x)\n}/\d+/g.toString() // /\\d+/gnew Date(2010,0,1).toString() // Fri Jan 01 2010 00:00:00 GMT+0800 (GMT+08:00)
当一个引用类型需要转换成数值类型时:
`如果引用类型有valueOf(),且方法返回一个基础类型,则将其转化成数值类型,然后返回`\
`否则,如果引用类型没有valueOf(),或者valueOf()返回的并不是一个基础类型,则调用toString()`\
`而valueOf()方法挺简单的,一般就返回对象本身,而Date类型的valueOf()会返回:1970年1月1日以来的毫秒数`\
`let d = new Date(2010, 0, 1)`\
`d.valueOf() //1262275200000`
来看这个例子:
function a(){
return 0
}
a.toString = function(){
return 1
}
console.log(a + '0') // 字符串'10'
console.log(a + 0) // 数值1
a + '0'时,很明显a需要转换成字符串,所以直接调用了我们给a重写的toString方法()
a + 0时,很明显a需要转换成数值类型,所以寻找a的valueOf,然后a没有valueOf方法,所以从原型链的上游Function类找valueOf,找到了该方法,然而a.valueOf()返回的不是数值类型,所以转而去调用a.toString()方法,返回了1
斯芬克斯卒,享年不详