JavaScript核心原理解析
周爱民
《JavaScript语言精髓与编程实践》作者,南潮科技(Ruff)首席架构师
立即订阅
3733 人已学习
课程目录
已完结 27 讲
0/3登录后,你可以任选3讲全文学习。
开篇词 (1讲)
开篇词 | 如何解决语言问题?
免费
从零开始:JavaScript语言是如何构建起来的 (5讲)
01 | delete 0:JavaScript中到底有什么是可以销毁的
02 | var x = y = 100:声明语句与语法改变了JavaScript语言核心性质
03 | a.x = a = {n:2}:一道被无数人无数次地解释过的经典面试题
04 | export default function() {}:你无法导出一个匿名函数表达式
05 | for (let x of [1,2,3]) ...:for循环并不比使用函数递归节省开销
从表达式到执行引擎:JavaScript是如何运行的 (6讲)
06 | x: break x; 搞懂如何在循环外使用break,方知语句执行真解
07 | `${1}`:详解JavaScript中特殊的可执行结构
08 | x => x:函数式语言的核心抽象:函数与表达式的同一性
09 | (...x):不是表达式、语句、函数,但它却能执行
10 | x = yield x:迭代过程的“函数式化”
11 | throw 1;:它在“最简单语法榜”上排名第三
从原型到类:JavaScript是如何一步步走向应用编程语言的 (6讲)
12 | 1 in 1..constructor:这行代码的结果值,既可能是true,也可能是false
13 | new X:从构造器到类,为你揭密对象构造的全程
14 | super.xxx():虽然直到ES10还是个半吊子实现,却也值得一讲
15 | return Object.create(new.target.prototype):做框架设计的基本功:写一个根类
16 | [a, b] = {a, b}:让你从一行代码看到对象的本质
17 | Object.setPrototypeOf(x, null):连Brendan Eich都认错,但null值还活着
从粗通到精通的进阶之路:唯一不变的是变化本身 (5讲)
18 | a + b:动态类型是灾难之源还是最好的特性?(上)
19 | a + b:动态类型是灾难之源还是最好的特性?(下)
20 | (0, eval)("x = 100") :一行让严格模式形同虚设的破坏性设计(上)
21 | (0, eval)("x = 100") :一行让严格模式形同虚设的破坏性设计(下)
22 | new Function('x = 100')();:函数的类化是对动态与静态系统的再次统一
不定期加餐 (3讲)
加餐 | 捡豆吃豆的学问(上):这门课讲的是什么?
免费
加餐 | 捡豆吃豆的学问(下):这门课该怎么学?
免费
加餐 | 让JavaScript运行起来
免费
结束语 (1讲)
结束语 | 愿你能做一个真正“懂”的程序员
JavaScript核心原理解析
登录|注册

18 | a + b:动态类型是灾难之源还是最好的特性?(上)

周爱民 2019-12-25
你好,我是周爱民,欢迎回到我的专栏。今天我们讲的主题是 JavaScript 的动态类型系统。
动态类型是 JavaScript 的动态语言特性中最有代表性的一种。
动态执行与动态类型是天生根植于 JavaScript 语言核心设计中的基础组件,它们相辅相成,导致了 JavaScript 在学习上是易学难精,在使用中是易用易错。成兹败兹,难以得失论。

类型系统的简化

从根底上来说,JavaScript 有着两套类型系统,如果仅以此论,那么还算不上复杂。
但是 ECMAScript 对语言类型的约定,又与 JavaScript 原生的、最初的语言设计不同,这导致了各种解释纷至沓来,很难统一成一个说法。而且,ECMAScript 又为规范书写而订立了一套类型系统,并不停地演进它。这就如同雪上加霜,导致 JavaScript 的类型系统越发地说不清楚了。
在讨论动态类型的时候,可以将 JavaScript 类型系统做一些简化,从根底里来说,JavaScript 也就是 typeof() 所支持的 7 种类型,其中的“对象(object)”与“函数(function)”算一大类,合称为引用类型,而其他类型作为值类型
无论如何,我们且先以这种简单的类型划分为基础,来讨论 JavaScript 中的动态类型。因为这样一来,JavaScript 中的类型转换变得很简单、很干净,也很易懂,可以用两条规则概括如下:
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《JavaScript核心原理解析》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(7)

  • Y
    这应该是由于对象类型转换为值类型时的拆箱操作导致的。
    []拆箱的话会先执行[].valueOf(),得到的是[],并不是原始值,就执行[].toString(),得到的结果是''。
    {}拆箱会先执行{}.valueOf(),得到的是{},并不是原始值,于是执行toString(),得到的结果是[object Object]。
    []+{}就相当于""+"[object Object]",结果就是[object Object]。
    {}+[]的话,js会把开头的{}理解成代码块,所以这句话就相当于+[],也就是等于+"",将空字符串转换为数字类型,结果就是0。
    {}+{}的话,也是和上面一样的道理,相当于+"[object Object]",将字符串转化为数字类型,结果是NaN。
    []+[]就相当于""+"",所以结果还是""。

    作者回复: 赞的。^^.

    今天的课程可以对答案哟。

    2019-12-25
    5
  • 王大可
    在chrome浏览器(版本 79.0.3945.88(正式版本) (64 位))计算 {} + {} 结果是"[object Object][object Object]"
    edge 下是计算 {} + {} 结果是 NaN

    作者回复: 确实。

    不过在浏览器的控制台上,和在引擎的层面上执行也是会有区别的。都是使用 v8,NodeJS在Shell中与chrome也一样。但是你写在.js文件中,或者直接从node的命令行上执行,效果就不一样了,例如:

    ```
    > node -p -e '{} + {}'
    NaN
    ```

    2019-12-26
    1
    1
  • 潇潇雨歇
    []和{}在转换为值类型时会先调用valueOf然后调用toString。
    1、[]+{},前者转换'',后者转换为[object Object],这里为字符串连接操作,所以结果为'[object Object]'
    2、{}+[],前者为代码块,后者+操作符将''转换为0,所以结果为0
    3、{}+{},前者为代码块,后者+操作符将'[object Object]'转换为NaN,因为它不能转换为一个正常的数值
    4、[]+[],前者为'',后者也为'',这里是正常的字符串连接,所以结果为''

    作者回复: 赞的,+1票。^^.

    今天的课程就分析这个了。

    2019-12-25
    1
  • sprinty
    在您的文章里,经常出现 "界面" 这个词,怎么理解呢?

    我简单的当做 "编程接口" 的近义词。

    作者回复: 是的。同义。

    只是我一直的工作是架构,所以架构中通用它的直译,也就是“界面”,而不是“接口/编程接口”,因为有些架构中的界面,并不是用编程来实现的。在这种情况下,界面更多的是一种规约。

    2019-12-25
    1
  • 晓小东
    老师对于下面两段话,我理解的不是很清楚 (没看出来,判断两次还是判断一次逻辑???)

    NOTE: 在 ECMAScript 6 之前,由于[PrimitiveValue]来存放对应的封装类。也就是说,只有当obj.[Class]存放着false值时,它才是false值所对应的对象实例。而 ECMAScript 6 将上述的依赖项变成了一个,也就是说只要有一个对象有内部槽[[BooleanData]],那么它就是某个 boolean 值对应的对象。这样处理起来就简便了,不必每次做两项判断。

    作者回复: ES6之前,是需要判断两次的。
    * 有[[PrimitiveValue]]内部槽,说明是一个用包装类得到的值。然后,
    * 查看[[Class]]内部槽,找到对应的包装类,从而知道类型。

    在ES6之后,由于每种包装类有独立的一个槽,所以如果对象obj有[[BooleanData]],那就说明了包装类是Boolean(),且被包装的数据在[[BooleanData]]槽中。

    2019-12-27
  • 鲜于.css
    js就是学不明白闭包和原型原型链
    2019-12-26
  • 晓小东
    老师有个问题, 既然您讲了数据的值类型与引用类型概念, 像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-25
收起评论
7
返回
顶部