isNaN(parseInt(new Date())) + Number([1]) + typeof undefined
@1. parseInt(new Date()) --> 时间对象转为字符串:调用其内置方法Symbol.toPrimitive,传参‘default’,得到字符串:"Fri Jul 23 2021 15:42:12 GMT+0800 (中国标准时间)"
@2. parseInt("Fri Jul 23 2021 15:42:12 GMT+0800 (中国标准时间)") --> NaN
@3. isNaN(NaN) --> true
@4. true + Number([1]) -->[1]转为数字的步骤:c查看有无Symbol.toPrimitive属性(数组没有这个属性),没有的话就与valueOf查找原始值(结果是[1],不是原始值),再走toString()地到字符串'1',最后Number(’1‘) -->1
image.png
@5. true + 1 + typeof undefined --> 1+1+'undefined'
@6. 最后结果是’2undefined‘
!(!'Number(undefined)')
@1. !/!! 会存在其他类型转为布尔类型值
@2. 'Number(undefined)'转为布尔类型是 true
@3. !!true --> true
parseFloat('1.6px') + parseInt('1.2px') + typeof parseInt(null)
@1. parseFloat('1.6px') --> 1.6
@2. parseInt('1.2px') -->1
@3. typeof parseInt(null) --> parseInt(null) --> 0
@4. typeof 0 --> 'number'
@5. 1.6 + 1 + 'number' --> '2.6number'
Boolean(Number('')) + !isNaN(Number(null)) + Boolean('parseInt([])') + typeof !(null)
@1. Boolean(Number('')) -->Number('')=0 --> Boolean(0) = false
@2. !isNaN(Number(null)) -->Number(null) == 0 --> !isNaN(0) = true
@3. Boolean('parseInt([])') --> true
@4. typeof !(null) -->!(null):null转成布尔类型是false --> !false = true --> typeof true = 'boolean'
@5. false + true + true + 'boolean' = '2boolean'
@6. 注意:parseInt和Number的处理机制不同,所以,parseIn([]) 与Number([]) 的结果也不通
把其他类型转为Number:https://www.jianshu.com/p/a36980234665
isNaN(Number(!!Number(parseInt('0.8'))))
@1. parseInt('0.8') --> 0
@2. Number(0) --> 0
@3. !!0 --> false
@4. Number(false) --> 0
@5. isNaN(0) --> false
6
!typeof parseFloat('0')
@1. parseFloat('0') --> 0
@2. typeof 0 --> 'number'
(typeof xxx :结果一定是字符串;
typeof 0 结果是 字符串number --> 'number';
typeof '1' --> 'string';
typeof {} --> '[object Object]')
@3. !'number' --> false
Number('') // 0
parseInt('') // NaN
image.png
16 + {}
@1. {}转为数字
@2. 先去检测有无Symbol.toPrimitive属性(经检测没有)
@3. 如没有再基于valueOf找原始值(经检测,不是原始值,是个对象)
@4. 再去调toString方法,结果是:‘[object Object]’
@5. 16 + ‘[object Object]’ :到这一步后,已经变成字符串拼接
@6. 最后结果‘16[object Object]’
{} + 16
结果是16,在对象的左边,没有其他操作(例如声明变量接受值等)此时浏览器是把当前操作分解成为两部分"{}代码块"和”+1 “,两部分之间没有关系息,所以结果是1
但凡用()包一下都不是这个结果
image.png
var n = 6
console.log((n++) + n-- + 5 + --n + --n)
console.log(n)
回忆下基础知识:
- i++ 和 ++i 都是自身基础累加1
- i=1
5+(i++) = ?
i = ?
i++ 是先拿原始值运算,运算完成后再自身累加1
所以:5 + 1(5加完1后,i累加1 变成2) = 6 - i=1
5+(++i) = ?
i = ?
++i 是自身先累加1,拿累加后的结果再进行运算
5 + 2(i自身先累加1,再进行运算) = 7
- i=1
- i++ 和 i + = 1 / i = i + 1 的区别
- i = '1' ;如果是字符串1
i++ 等于 2 ; '++' 一定是数学运算
i = i + 1 或者 i + = 1 等于 '11'
i = i + 1 或者 i + = 1 可能会出现字符串拼接
- i = '1' ;如果是字符串1
解析:(n++) + n-- + 5 + --n + --n
@1、(n++):拿初始值6计算,这一步走完,n累加1,变成7
@2、6 + n-- :n已经变成7,所以是6+7,执行完这一步,n减一,变成6
@3、 6 + 7 + 5 + --n:--n先减一,再计算,所以n 变成5
@4、6 + 7 + 5 + 5 + --n:--n先减一,再计算,所以n 变成4
@5、6 + 7 + 5 + 5 + 4 = 27,n=4
var str = 'abc123'
var num = parseInt(str)
if (num == NaN) {
alert(NaN)
} else if(num == 123) {
alert(123)
} else if (typeof num == 'number') {
alert('number')
} else {
alert('str')
}
这个比较简单,parseInt([val]):[val]必须是字符串,parseInt会从左到右依次查找有效数字,遇到无效数字就停下不在查找
本题中,第一个就是字母a,所以停止查找,相当于一个有效数字都没有,所以结果是NaN
typeof NaN 结果是 'number'
所以alert 'number'
小知识点:alert出的值,都是转为字符串再输出的
alert(1) --> '1'
if(isNaN(NaN) == '') {
console.log('zhangsan')
} else {
console.log('lisi')
}
@1、isNaN(NaN) --> true
@2、true == ‘’ :需要两边都转成数字再比较
@3、true --> 1 转成数字是1
@4、‘’ --> 转成数字是0
@5、 1== 0 条件不成立,所以输出‘lisi’
相关链接:https://www.jianshu.com/p/eb2c41d0bbea
/ var a = ?
if (a == 1 && a == 2 && a == 3) {
console.log('ok')
}
a 等于什么,下边的判断才会成立?
分析:
@1、 如果数据类型转换比较熟悉,那么看到'==' 比较,想到[类型转换]。
@2、"=="比较时的互换规则: https://www.jianshu.com/p/eb2c41d0bbea
@3、如果a是字符串或者数字 那么a就是一个固定值,条件不成立
@4、所以只能a是个对象,因为对象转数字的流程是:
Symbol.toPrimitive --> valueOf() --> toString
把其他数据类型转型为Number:
https://www.jianshu.com/p/a36980234665
@5、我们就可以通过重写对象的Symbol.toPrimitive / valueOf / toString中的任何一个属性 来达到想要的效果
先来重写对象的Symbol.toPrimitive(普通对象并没有内置Symbol.toPrimitive属性,但是可以重写)
var a = {
i : 0,
[Symbol.toPrimitive]() {
return ++this.i
}
}
if (a == 1 && a == 2 && a == 3) {
console.log('ok')
}
image.png
已知对象转数字的流程,所以重写Symbol.toPrimitive/valueOf/toString,结果是一样的
image.pngimage.png
image.png
再看一个类似的解法
var a = [1,2,3]
a.toString = a.shift
if (a == 1 && a == 2 && a == 3) {
console.log('ok')
}
image.png
其实和上边是同一个原理,通过重写toString来实现
a每次调toString的时候,就把a数字的第一个删掉并且返回.....
以上都是基于类型转换实现的,下边再从另一个方向分析一下
@1、声明a变量是在全局上下文中,而且是基于var处理的,此时可以想到['GO' --> window]
堆栈内存及栈结构:https://www.jianshu.com/p/2ef9f7983907
@2、所以我们使用的a是window的属性
@3、所以我们要用a的时候是从window下取出的,此时可以联想到对象数据劫持:Object.defineProperty
@4、 当劫持window下的a的时候,会触发getter函数,此时在getter函数中返回我们想要的值
var i =0
Object.defineProperty(window, 'a' ,{
// 获取window中a属性的值,会触发getter函数
get() {
return ++i
}
})
if (a == 1 && a == 2 && a == 3) {
console.log('ok')
}
image.png
’‘
实现方法也不止这几种,后续再补充吧
网友评论