18 | a + b:动态类型是灾难之源还是最好的特性?(上)
该思维导图由 AI 生成,仅供参考
类型系统的简化
- 深入了解
- 翻译
- 解释
- 总结
JavaScript的动态类型系统是其最具代表性的特性之一。本文深入探讨了JavaScript类型系统的复杂性和简化规则。作者指出,JavaScript的类型系统可以简化为7种类型,其中的“对象”和“函数”被合称为引用类型,其他类型则为值类型。在讨论动态类型时,文章提出了两条简单的类型转换规则,即从值到引用调用Object(x)函数,从引用到值调用valueOf()方法或值类型的包装类函数。文章还强调了从值到引用的转换相对容易,因为主要的值类型都有对应的引用类型,可以通过简单方法一一对应地将它们转换过去。作者还详细介绍了使用Object(x)函数进行转换的安全性和灵活性。此外,文章还讨论了ECMAScript 6中新增的Symbol.toPrimitive符号以及原始值与对象类型之间的关系。总的来说,本文全面探讨了JavaScript的动态类型系统,展现了其复杂性和简化规则,为读者提供了对JavaScript类型系统的深入了解。 文章还讨论了ECMAScript 6中新增的Symbol.toPrimitive符号以及原始值与对象类型之间的关系。此外,文章还讨论了ECMAScript 6中新增的Symbol.toPrimitive符号以及原始值与对象类型之间的关系。文章还讨论了ECMAScript 6中新增的Symbol.toPrimitive符号以及原始值与对象类型之间的关系。文章还讨论了ECMAScript 6中新增的Symbol.toPrimitive符号以及原始值与对象类型之间的关系。
《JavaScript 核心原理解析》,新⼈⾸单¥59
全部留言(12)
- 最新
- 精选
- Y这应该是由于对象类型转换为值类型时的拆箱操作导致的。 []拆箱的话会先执行[].valueOf(),得到的是[],并不是原始值,就执行[].toString(),得到的结果是''。 {}拆箱会先执行{}.valueOf(),得到的是{},并不是原始值,于是执行toString(),得到的结果是[object Object]。 []+{}就相当于""+"[object Object]",结果就是[object Object]。 {}+[]的话,js会把开头的{}理解成代码块,所以这句话就相当于+[],也就是等于+"",将空字符串转换为数字类型,结果就是0。 {}+{}的话,也是和上面一样的道理,相当于+"[object Object]",将字符串转化为数字类型,结果是NaN。 []+[]就相当于""+"",所以结果还是""。
作者回复: 赞的。^^. 今天的课程可以对答案哟。
2019-12-25330 - 王大可在chrome浏览器(版本 79.0.3945.88(正式版本) (64 位))计算 {} + {} 结果是"[object Object][object Object]" edge 下是计算 {} + {} 结果是 NaN
作者回复: 确实。 不过在浏览器的控制台上,和在引擎的层面上执行也是会有区别的。都是使用 v8,NodeJS在Shell中与chrome也一样。但是你写在.js文件中,或者直接从node的命令行上执行,效果就不一样了,例如: ``` > node -p -e '{} + {}' NaN ```
2019-12-2623 - 潇潇雨歇[]和{}在转换为值类型时会先调用valueOf然后调用toString。 1、[]+{},前者转换'',后者转换为[object Object],这里为字符串连接操作,所以结果为'[object Object]' 2、{}+[],前者为代码块,后者+操作符将''转换为0,所以结果为0 3、{}+{},前者为代码块,后者+操作符将'[object Object]'转换为NaN,因为它不能转换为一个正常的数值 4、[]+[],前者为'',后者也为'',这里是正常的字符串连接,所以结果为''
作者回复: 赞的,+1票。^^. 今天的课程就分析这个了。
2019-12-253 - 晓小东老师有个问题, 既然您讲了数据的值类型与引用类型概念, 像weakSet与weakMap 对对象的弱引用该如何理解, 这个弱引用到底是个啥。
作者回复: 弱引用是向weakSet/weakMap中添加一个目标对象的引用,但添加是目标对象的引用计数不增加。比较来说: ``` var x = {}; // <-右边的对象字面量的引用计数加1 var y = x; // <- 再加1 weakSet.add(x); // <-不加1 weakSet.add(y); // <-也不加1 delete x; // 减1 delete y; // 再减1 ... ``` 到这里,由于对象的引用计数为0了,所以weakSet中的那个被add()进去的x、y就自动被回收了。——weakSet/weakMap具备这种机制。 所以weakSet/weakMap没有size这个属性,它不安全。——你刚读了它的值,它自己自动回收了一下,就又变掉了。
2019-12-253 - 晓小东老师对于下面两段话,我理解的不是很清楚 (没看出来,判断两次还是判断一次逻辑???) NOTE: 在 ECMAScript 6 之前,由于[PrimitiveValue]来存放对应的封装类。也就是说,只有当obj.[Class]存放着false值时,它才是false值所对应的对象实例。而 ECMAScript 6 将上述的依赖项变成了一个,也就是说只要有一个对象有内部槽[[BooleanData]],那么它就是某个 boolean 值对应的对象。这样处理起来就简便了,不必每次做两项判断。
作者回复: ES6之前,是需要判断两次的。 * 有[[PrimitiveValue]]内部槽,说明是一个用包装类得到的值。然后, * 查看[[Class]]内部槽,找到对应的包装类,从而知道类型。 在ES6之后,由于每种包装类有独立的一个槽,所以如果对象obj有[[BooleanData]],那就说明了包装类是Boolean(),且被包装的数据在[[BooleanData]]槽中。
2019-12-272 - undefinedChrome 90.0.4430.85 中(非 DevTools) 创建 index.html 和 app.js app.js -> console.log({} + {}) 的值竟然也是 "[object Object][object Object]"
作者回复: 在之前的回复中说过这个问题。如下执行测试: ``` > node -p -e '{} + {}' NaN ``` `-e`参数用于直接执行,而不是作为模块执行。
2021-04-2541 - undefined#提个小问题# 原文中 「一共就有了 5 个对应的私有槽:[[BooleanData] [[NumberData]]、[[StringData] [[SymbolData]]和[[BigIntData]]」 修改为 一共就有了 5 个对应的私有槽:[[BooleanData]]、[[NumberData]]、[[StringData]]、[[SymbolData]] 和 [[BigIntData]] 要好一些。 原文少了顿号,缺少了两个 ] 符号,中文和英文之间加上一个空格要美观些(个人感受)。
作者回复: 多谢多谢。^^. 刚才我查了一下md原稿,原文是没错的。不过这个改起来有点困难。内容网页是用markdown自动生成的,估计极客时间用的也是第三方的生成组件,然后自动吞掉了……
2021-04-251 - HoSalt「由于[PrimitiveValue]来存放对应的封装类。也就是说,只有当obj.[Class]存放着false值时」 ES6之前PrimitiveValue里面放的对象(封装类),ES6后 [[xxxData]]里面放的是值还是封装类,若放的封装类,那值依旧放在obj.[Class]? 不太明白PrimitiveValue为什么要放封装类,直接放基本类型不就行了吗?
作者回复: ES6之前是两个私有域 [[Class]] [[PrimitiveValue]] 而ES6之后是一个。以String(5)为例,那么就是: [[StringData]] 但是由于传入参数是数字5,所以 [[StringData]]里存放的是转换后的字符串值"5",同样的原因,如果是ES5那么[[PrimitiveValue]]也存放的是字符串值"5",而[[Class]]将存放String这个类的引用。 在ES5里面,Boolean/String/Number只使用了一种结构,三种对象的内部结构是一样的;在ES6里面,是三种不同的变体对象(结构/内部槽是不一样的)。这是两种不同的设计思路。至于为什么要放转换后的值,是因为创建这个对象是一次性的,而使用是多次的,所以预先转换的效率高。
2020-05-251 - weineel在您的文章里,经常出现 "界面" 这个词,怎么理解呢? 我简单的当做 "编程接口" 的近义词。
作者回复: 是的。同义。 只是我一直的工作是架构,所以架构中通用它的直译,也就是“界面”,而不是“接口/编程接口”,因为有些架构中的界面,并不是用编程来实现的。在这种情况下,界面更多的是一种规约。
2019-12-251 - FG佳周老师 的《程序原本》棒棒的,里面刻舟求剑的印象非常深2020-07-132