javaScript的数据类型的一些细节

112 阅读3分钟
  1. typeof null === 'object' 在javascript中数据在底层的存储都是以二进制的形式进行存储的,javascript会把二进制前三位数为0的判断为Object类型,由于null在底层存储都是0,因此,使用typeof进行检测的时候会得到typeof null为object类型。

事实上,javascript的数值是已32位字节进行存储的,这个数值又可以分为两个部分,一个标记位,通常有1-3个字节表示,另一个是数值。

以下就是javascript中个数据类型的标记位:

  • 000:object
  • 1:integer --整型
  • 010:double
  • 100:String
  • 110:Boolean

如何判断null?

let obj1 = {}
let obj = null

if (!obj && typeof obj === 'object') {
    console.log('我是null', obj)
}

if (obj1) {
    console.log('我是空对象', obj1)
}
    • 运算符转为数字类型
function toNumber(val) {
    const result = + val
    console.log('输出结果', result)
    return result
}

toNumber({}) // NaN
toNumber(null) // 0
toNumber('111') // 111
toNumber(1) // 1
toNumber(true) // 1
toNumber(undefined) // NaN

// es6的bigInt和Symbol
toNumber(10n)  // TypeError: Cannot convert a BigInt value to a number
toNumber(Symbol.for('a')) // TypeError: Cannot convert a Symbol value to a number
  1. parseInt() 的第二个参数表示的是进制,取值范围为2到36(parseInt - JavaScript | MDN (mozilla.org))
const result = ['1', '2', '3'].map(parseInt)

console.log(result)

result.map((item, index) => parseInt(item, index))

/* 相当于执行
parseInt('1', 0) // 1
parseInt('1', 0) // NaN
parseInt('1', 0) // NaN
*/
/* 
布尔值为false的有:
+0, -0, 0, false, '', undefined, null, NaN
*/
  1. == 隐式转换
/* 
宽松比较:
1. NaN 和任何数据类型包括它自己都不能在==下成立
2. bigInt 和 Symbol 这两个只有在同类型情况下才会相等
3. null 和 undefined 在== 成立,并且自身也成立  
4. 布尔值和其他类型进行比较的时候会转成数字在进行比较
5. 数字类型和其他类型进行比较的时候会转换成数字在进行比较
6. 对象和原始数据类型进行比较的时候,对象会转换成原始数据类型
7. 对象和对象进行比较的时候,比的是引用地址
 */
 
console.log(NaN == 1)  // false
console.log(NaN == NaN) // false
console.log(null == null) // true
console.log(undefined == undefined) // true
console.log(null == undefined) // true

console.log(null == 0) // fasle
console.log('0' == false) // true
  1. undefined 和 null 的区别
console.log(Object.getOwnPropertyDescriptor(global, 'null'))
// undefined

console.log(Object.getOwnPropertyDescriptor(global, 'undefined'))
/* 
{
  value: undefined,
  writable: false,
  enumerable: false,
  configurable: false
}
*/
  1. NaN的注意点
1. typeof 是数字
2. NaN == NaN 的值为false
3. 不能被删除
*/

console.log(Object.getOwnPropertyDescriptor(global, 'NaN'))

 /* 
 { value: NaN, writable: false, enumerable: false, configurable: false }

 他的configurable的值为false,因此不能被删除
 */

// 判断是否为NaN的几种方法

function isNaNVal(val) {
    return Object.is(val, NaN)
}

function isNaNVal(val) {
    return val !== val
}

function isNaNVal(val) {
    return typeof val === 'number' && isNaN(val)
}

// 综合垫片
if (!('isNaN' in Number)) {
    Number.isNaN = function (val) {
        return typeof val === 'number' && isNaN(val)
    }
}


/* Object.is(value1, value2) 
可以用来判断value1 和value2 是不是同一个值,可以区分-0和+0 
*/
  1. 二元操作符 + 的注意点 {} + {} 、{} + [] 、[] + []、[] + {}
// 二元操作符 + 的规则

/*
1. 如果操作数是对象,就会把对象转换为原始值

2. 如果其中一个操作是字符串,另一个操作数也会转换成字符串,进行字符串的拼接

3. 否则,两个操作数将转换成数字或者NaM, 进行加法操作 

*/

/* 注意点: 
1. 10n + 10
2. Symbol.for('a') + 10
 */

// console.log(10n + 10) // TypeError: Cannot mix BigInt and other types, use explicit conversions
// console.log(Symbol.for('a') + 10) // TypeError: Cannot convert a Symbol value to a number


/* 对象转换为原始的类型值的方法:依次进行转换,直到找到原始值为止
1. Symbol.toPrimitive()
2. Object.prototype.valueOf()
3. Object.prototype.toString() 
*/

// 1. {} 的原始值
console.log({}[Symbol.toPrimitive]) // undefined

console.log({}.valueOf()) // {}

console.log({}.toString()) // [object Object]

/* 
所以,最终{} 的原始值为'[object Object]'
*/


// 2. [] 的原始值
console.log([][Symbol.toPrimitive]) // undefined
console.log([].valueOf()) // []
console.log([].toString()) // ''

/* 
所以,最终[] 的原始值为''
*/

console.log([] + []) // ''
console.log([] + {}) // '[object Object]'
console.log({} + {}) // '[object Object][object Object]'

console.log({} + []) // 0

console.log({} + '') // 0

console.log('' + {}) // '[object Object]'

console.log({} + 0) // 0

console.log(0 + {}) // '0[object Object]'

console.log([] + '') // ''
console.log('' + []) // ''

console.log([] + 0) // '0'

console.log(0 + []) // '0'

/* 
{} + {} 这种在浏览器中的运算就相当于({} + {}) ==> ('[object Object]' + '[object Object]')

{} + [] 这种的运算在浏览器中就相当于{}; + [] ===> + [] ===> + '' 结果就得到0

[] + 0 这种的运算[]不能看做一个语句的结尾,因此依然是 '' + 0

*/