19 | a + b:动态类型是灾难之源还是最好的特性?(下)
该思维导图由 AI 生成,仅供参考
集中精力办大事
- 深入了解
- 翻译
- 解释
- 总结
JavaScript类型转换机制是一个复杂而深奥的话题,本文通过深入讨论类型转换的规则和特殊情况,帮助读者更好地理解JavaScript中的类型转换机制。文章首先介绍了类型转换的规则和主要类型,然后深入讨论了在JavaScript中“加号(+)”运算符的特殊性,以及对象到原始值的转换过程。通过详细的步骤分析,解释了对象和数组相加在特定情况下会出现不同结果。此外,还介绍了JavaScript中的预期和非预期情况下的类型转换结果,以及显式和隐式转换的区别。文章还讨论了字符串在“+”号运算中的优先权和Date类中的特殊处理方式,最后提到了Symbol.toPrimitive的处理对隐式转换逻辑的影响。总之,本文通过深入分析JavaScript中的类型转换机制,为读者提供了深入理解JavaScript类型转换机制的视角,具有技术深度和实用价值。
《JavaScript 核心原理解析》,新⼈⾸单¥59
全部留言(16)
- 最新
- 精选
- weineel强行找到一种方法, 但和本节所讲没啥关系: Object.defineProperty(global, 'x', { get: function() { return Math.random(); } }) x === x // false
作者回复: 赞! 的确,这是除NaN之外我认为最可行的一个答案。事实上,这也是我在课程中提升“动态语言特性”这个方向的原因:一部分动态特性是基于OOP来实现的,这正是JavaScript的混合语言特性的应用。 不过这个例子其实可以变成更简单。例如: ``` Object.defineProperty(global, 'x', { get: Symbol }) // 或 Object.defineProperty(global, 'x', { get: Math.random }) ``` AND, @晓小东 给出的Symbol()方案对这个getter方法是一个很好的补充,很好地利用了“symbol总是唯一”的特性。
2019-12-27211 - 陈强这里是一个拓展阅读:https://2ality.com/2012/01/object-plus-object.html 为什么{} + {} 在浏览器中打印的是 "[object Object][object Object]" 因为“the Node.js REPL parses its input differently from either Firefox or Chrome (which even uses the same V8 JavaScript engine as Node.js). The following input is parsed as expressions and the results are less surprising:” 实际上chrome自己加了console.log(),相当于({} + {}),firefox的控制台会输出NaN。 // test in chrome {} + {} // "[object Object][object Object]" {} + {} === "[object Object][object Object]" // false ({} + {}) === "[object Object][object Object]" // true
作者回复: 谢谢 👍+3
2020-04-088 - Geek_185c7d请问老师,为什么{} + {} 在浏览器中打印的是 "[object Object][object Object]"
作者回复: 浏览器把引擎包了一层,你执行的不是真正的引擎环境。 在node中用如下命令行试试: ``` > node -p -e '{} + {}' NaN > node -p -e '{} + []' 0 ```
2020-01-1934 - 晓小东难道是这个吗, 如果作为标识符var x 确实没想出。 >> Symbol() === Symbol() // false
作者回复: 参见 @sprinty 的答案。呵呵,我自己也不知道有没有更多的可能了。
2019-12-282 - 清波老师您好,我在浏览器控制台,node环境控制台或者代码中:{} + {}的执行结果都是"[object Object][object Object]",但是教程中的结果是NaN,是不是还有其他理解方式?
作者回复: 评论中有解说过这个问题,是node/控制台包过一次。可以用用如下命令行试试: ``` > node -p -e '{} + {}' NaN > node -p -e '{} + []' 0 ```
2022-01-071 - undefined> node -v v12.20.1 > node -p '{} + {}' NaN > node -p '({} + {})' [object Object][object Object] > node -p "eval('{} + {}')" NaN > node -p "eval('({} + {})')" [object Object][object Object]
作者回复: 这个?问题是? 1、3是按语句执行,所以是NaN;2、4是按表达式执行,所以是[object Object]*2。 正文中(解题2)说的都是第一种情况。而第二种情况的分析路径在正文中也是交待了的哦。
2021-04-301 - wheatup和sprinty的方法类似,只不过避免了污染全局作用域: with ({ get x() { return Symbol() } }) { console.log(x === x); // false } 这个能成功的原因是这里的 x 其实是有 [withObj].x 取值的一个操作,然后利用getter返回不同的值造成的。 --- 真要说利用本节课学到的内容的话,可以把题目的 x === x 换成 x >= x,单纯的x === x是不会触发隐式类型转换的,而js在比较大小时一定会将对象转换成数值再进行比较,所以这里就会调用[Symbol.toPrimitive],这时候就可以重写这个方法做些手脚: let x = { [Symbol.toPrimitive]() { return Math.random(); } }; console.log(x >= x); // true和false都有可能
作者回复: +1
2020-06-101 - 油菜老师,Number([]) == Number([]) 是true,但[] == [] 是false,动态类型转换如何解释这个案例呢? ------------ var x = []; x === x // true; x === [] // false; [] === x // false; [] === [] //false;
作者回复: 对于`Number([])`来说,过程如下: ==== Number([]) => Number(ToNumber(ToPrimitive([]))) => Number(ToNumber([].valueOf())) => Number(ToNumber('')) => Number(0) => 0 ==== 注意这里的结果值是一个值类型,而不是对象类型,所以`typeof Number([])`的值将是"number"。所以,第一个式子等义于`0 == 0`,当然是true。 对于`[] == []`来说,两个对象实例的比较总是false。
2020-11-19 - HoSalt「Date() 类中仍然是会调用 toString 或 valueOf 的,这是因为在它的Symbol.toPrimitive实现中仅是调整了两个方法的调用顺序,而之后仍然是调用原始的、内置的ToPrimitive()方法的」 调整顺序是值hint值为default的情况下?
作者回复: 是。如果hint不是default,那么就相当于指定顺序了。 https://tc39.es/ecma262/#sec-toprimitive
2020-05-25 - K4SHIFZ自动分号插入并不会将{}+{} 变成{};+{} 吧?因为没有行结束符。
作者回复: 会的。:)
2020-03-282