JavaScript核心原理解析
周爱民
《JavaScript语言精髓与编程实践》作者,南潮科技(Ruff)首席架构师
立即订阅
3529 人已学习
课程目录
已更新 16 讲 / 共 21 讲
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是如何一步步走向应用编程语言的 (1讲)
12 | 1 in 1..constructor:这行代码的结果值,既可能是true,也可能是false
不定期加餐 (3讲)
加餐 | 捡豆吃豆的学问(上):这门课讲的是什么?
免费
加餐 | 捡豆吃豆的学问(下):这门课该怎么学?
免费
加餐 | 让JavaScript运行起来
免费
JavaScript核心原理解析
登录|注册

开篇词 | 如何解决语言问题?

周爱民 2019-11-11
00:00
10:26
讲述:周爱民 大小:9.56M
你好,我是周爱民,和你一样,我喜欢 JavaScript。
我是《JavaScript 语言精髓与编程实践》这本书的作者,这个书名正好也刻画了我追随 JavaScript 的轨迹:在过去的二十年中,我一面研究它的语言精髓,一面做编程实践。
曾经在很长的时间里面,我的脑海中时常会有一个闪念:如何解决语言问题?这也伴随着强烈的自我否定与置疑,因为它的潜台词是:我还没有搞定语言问题。

问对问题

在那之前,我是从 DBASE 这个数据库入手,从类似 SQL 的语言开始学习的。第一门正式学习的语言是汇编,然后是 Basic 和 Pascal。后来在商用产品开发的环境中,我选择了 Delphi 这门语言。这一段语言学习的经历,直到 2003 年前后戛然而止,那时我写完了我的第一本书,名字就叫《Delphi 源代码分析》。
这些是我既有的语言知识,一定程度上来说,它限制了我对 JavaScript 的进一步学习,既成习惯的思维方式和知识体系盘根错节,渗透极深。
我是从 1998 年左右就开始接触 JavaScript 这门语言的,然而直到五六年之后,我仍然在使用 Delphi 中的面向对象概念与理论来理解与分析 JavaScript 的对象模型。这也是我早期做 WEUI 这个项目时的困扰:我一面努力改造着 JavaScript 这门语言,一面又被它所左右。
那个时代,有太多人做着与我相似的事情:要上线一个大的前端产品,就先写一个框架或库,将传统语言中的经验复制过来。那些是我们的既得财富,闪烁着记忆的光芒、知识的火花,是自我价值和薪资价格的体现,所以它们是不可抛弃的、不可否认的、不可亵渎的。
在类似于此的、固化的思维里面,我们勤劳地、不知疲倦地写着新代码,而究其原因,只是我们不愿意丢弃那些旧代码而已。
如此负重前行,以至于让我不得不怀疑,自己是否还有能力把握这门“世界上最被误解的语言”。这是 Douglas Crockford(就是创建了 JSON 格式那位大牛)在 2001 年说过的话。
我真正下定决心抛弃所有,来重新理解这门语言的时候,是在我写出《Delphi 源代码分析》之后不久。这个时候,Borland 破产了,Delphi 被卖掉了,而我也做了架构师。此时,那些既有的经验,以及对语言孰优孰劣的固执已见都变得可有可无了。这时,对于我一直以来的困惑,我才真正地问对了第一个问题:
JavaScript 到底是一门什么样的语言?

语言

我常常说,问对了问题,也就有了“解”。
在 JavaScript 诞生的时候,主流的应用开发语言大多是静态的,以及单一语言类型的。当时面向对象编程大行其道,众多语言都纷纷以“我最 OOP”为宣传噱头,以及将它想像成语言发展的必然方向。随着 Java/JVM 的成熟,使用中间指令集 + 虚拟机来运行的语言环境也变得流行起来,因此一个虚拟机上跑很多种语言也就成了常态。但即使如此,具体到每一种语言,其主要特性还是单一的,并且通常以保持“语言特性的纯净”为已任。
JavaScript 却是一个异类,它最开始是一门“简单”的小语言,没有丰富的语言特性,也没有大一统的野心,更没有“包打天下”的虚拟机引擎。为了维护这种“小而简洁”,当然,另一部分原因也在于它的创世者太过匆忙和随意——它只实现了一些基础的语言特性,而没有从根本上“陈述”自己的设计原则与理念。
这门语言非常摇摆,在面向对象火的时候,它说“我是 OOP 的语言”;在函数式语言呼声渐高的时候,它又说“我是函数式的”。另外,你知道的,它天生还是一门动态的语言。不过,它也还包括一些静态的、结构化的语言成分。
支持这门语言挣扎求生、一路行来的,正是这门语言最初的、最精彩的设计:它是一门多范型语言,或者,也称为混合范型语言JavaScript 的简单来自于此,复杂也来自于此;生存能力来自于此,抨击诟病也来自于此。
的确,如果我不抛开 Delphi 语言给我留下的历史包袱,我还是能从 JavaScript 中看到我熟悉的、引以为傲的经验闪光,并让这些东西迅速激活我对语言的兴趣和掌控感。然而只需要稍稍多一点点时间,混合语言中的其它组分就会变成我的困扰,变成这门语言给我带来的种种陷阱,变成我近乎绝望的自我怀疑。
而其实问题的求解也很简单:不要试图去纯化这门语言。

语言的特性

所以在这个专栏里面,我就想与你讲一讲我对 JavaScript 各种语言特性的理解,还有展示将这些语言特性和语言范型融合如一的具体挑战与折衷。
JavaScript 主要包括 5 个方面的语言特性:结构化编程、面向对象编程、动态语言、函数式语言和并行语言。因此在这个专栏中,我将以“语言”为核心,主要讨论语言设计,结构化和面向对象特性,以及部分的动态语言特性。还有一些其它部分的特性,我将会在以后的专栏中再给你讲。
在讲述的内容方面,尽管每一讲都是一个独立的标题,但总体来说,这些内容也是循序渐进的,因此你最好不要落下课程。并且如果有时间、有机会的话,还是对前面的内容做一些分析和巩固为好。
另外,你可能已经注意到了:每一讲的标题都是一行代码。尽管这些代码绝大多数都是有意义的、可以使用的,但是我并不是从实用性出发来写出这些代码的,因此它们不见得能很好地使用在你的项目中。我尽量使每一讲的标题在表达多种语言特性的同时,指向一个主要的、核心的内容讲述方向。
事实上,如果你看到那样的一行标题后,能猜出它涉及到哪些混合语言特性,或者是由哪些特性共同作用以导致这个代码的形式风格或可能的结果,那么你也就相当于复盘了你的知识储备,这有助于你建立自己的知识体系。
所以,你大可以将这样的标题当做一把念珠,没事的时候,盘一盘。:)

体系性

说到体系性,其实这才是我这个课程最关注的地方。
我希望综合这些代码的特殊性,代码所涉问题的领域,代码的逐步分解解析,以及辨析与该代码相似的或同类的问题,一方面发掘它们潜在的应用,另一方面,则在于帮助你构建一个语言知识结构。这样的语言知识结构,能让你看到曾经摸过的那些项目,写过的那些代码,填过的那些巨坑的影子,并且发掘暗影背后涌动的语言原力,找到属于自己的、可规划的语言学习体系。
你不需要精通所有的语言,但如果你了解那些语言类型的核心的、本质的差异,建立起自己的对语言的认识观和辨析力,那么当你接触到一门新的语言时,便可以在极快的时间内将它纳入自己的语言知识结构,快速地映射到那些历史项目和研发经验中。你可以通过想象,将新的语言在自己的经验中“回放一遍”,这相当于用新语言重写了一遍那些代码,也相当于将你自己的历史经验全部消化在这个新语言之中。
这样的语言学习和感悟方法,收效是极快的。
我曾经在豌豆荚的工作中,完成过一个用 Lua 来实现的、支持大规模并发的服务端项目,那是一个金融级的风控产品。在我对 Lua 了解几乎为零的情况下,出于对“编程语言核心原理”的了解,通过上述知识映射的方法,我在零学习的情况就开始了编码工作。除了必要的查手册之外,切换语言的时间成本几乎可以忽略不计。
当然,听到这里的时候,你可能会说“Lua 和 JavaScript 的相似性太高”,又或者说“Lua 太简单了”。但是事实上,我之前在学习 Erlang 的时候也是如此,以及后来在学习 Scala 的时候仍然是如此。当你真正地“解决了语言问题”时,“新语言”真的对你来说完全不能称其为问题。
所谓的语言特性,其实是对语言的核心抽象概念的语法表现。所以,所谓的“学习新语言”,只不过是在玩“变换代码风格”的游戏,而已。
一旦你建立了你的体系性,那么相当于你创建了游戏规则,你就成了“编程游戏”中的上帝。
你将会有一种切实的、万物如一的操控感。

学这门课

所以,这门课的内容大概率不会用在你的一个线上项目中,也不会提高你写代码的速度。但它绝对能让你提升对代码的洞察力,让你可以在纷繁的代码中快速找到它在性能、组织、逻辑等这些方面的问题关键,也可以在语言层面给出合理的解释。
当然,就一个具体问题的具体解,这一切还是不够的,因为语言是实现业务的工具,而不是业务本身。所以,在面试中不仅仅会考察你的语言能力,也会考察你对曾经项目的经验与感受。
无论如何,我希望你能找到自己对语言的认识,无论是不是通过这门课程,“构造认识”对你自己而言都是极致重要的事情。如果在这其中,我的课程能对你有所帮助,那怕仅仅是一点点启发,我想,这都是我非常乐意看到的结果了。
最后,多谢你来看我的专栏。关于 JavaScript,你的理解是怎样的呢?你又有什么样的期待?欢迎留言。
取消
完成
0/1000字
划线
笔记
复制
unpreview
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《JavaScript核心原理解析》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(40)

  • crown
    老师好,我工作主要用node. js开发游戏服务器和web服务器的,按照我对操作系统的理解,单线程容易写对逻辑,非阻塞io如文件操作等+ epoll可以实现异步io,开多进程可以利用多核心。 可是大家都说node是单线程做游戏服务器不行,但是游戏逻辑不太好用多线程表达吧。。。 说node不适合写游戏服务器,主要说是js运行效率的缺陷?

    作者回复: 在涉及纯计算效率的问题上,js确实是要差一些的,要不然也不会专门再弄出一个BigInt类型出来,以及还有所谓的TypedArray。但是,如果仅仅是说能不能做游戏服务器,开发游戏应用代码,那么坦率的说:1、没问题,2、效率还错,3、开发挺快的;4、网络实现也很简洁……但是如果游戏需要处理传输层的编解码,等等与计算效率相关的情况,那么(前面已经说过了)就得换方案了。

    你提到多线程问题,对于最新的Node.js来说,原生多线程也是内置的了,但并不比传统开发工具下的简单。——所以除了语言或工具的习惯性之外,它也并没有什么优势。另外,在线程操作这个层级上,大家提供的都是差不多的核心操作或API,所以使用复杂度,面临的问题集之类的也差不多。只不过,相对于其它语言或应用环境,Node.js缺少在多线程基础上的开发库,这方面基本为0。

    最后,还是从纯语言的角度上来回答你的问题。事实上决定它合不合适写游戏的,根本之处(从语言的角度上来讲)与你所提的绝大多数特性都无关。如果游戏规模大一些,那么就不适合直接用JavaScript来开发了。在任何的、包括游戏开发在内的大型的应用开发中,JavaScript最大的缺陷其实是缺乏静态类型声明与检查。在动态类型体系下开发大型程序几乎是一种灾难,即使你再能控制类型的使用、团队的编码习惯等等,都很难避免。

    因此如果你非得在这种场景下使用JavaScript,我非常建议你考虑TypeScript,哪怕是Flow也行。当然,最终运行的执行环境仍然可以是Node.js,这就是个效率问题了,而与语言无关。

    2019-11-12
    9
  • 小伟
    js是我最早接触的语言,也是一直敬畏的语言,你以为掌握了,但在debug的时候,error会给你致命一击
    2019-11-11
    9
  • 烤迪
    老师可以推荐一些有利于洞悉语言本质的书吗,可以结合专栏阅读或者后面继续学习的书

    作者回复: 裂墙推荐。^^.
    https://github.com/aimingoo/my-ebooks#程序原本

    老实讲,比这里用js来讲的内容要易读得太多了。这里讲js吧,我还得注意“js/ecma到底如何实现”,或者这个特性那个特性什么的。而《程序原本》里只讲本质就好了。^^.

    2019-11-15
    1
    6
  • ssala
    接触的语言中,js是唯一一门让我头大的语言,打算跟随老师一起学习。
    2019-11-12
    2
    3
  • 温晓东
    爱民开课 支持 希望看见更多的课

    作者回复: 谢谢支持✊

    2019-11-12
    3
  • 张三
    老早就看了爱民老师的绿皮书。两个字“牛B”。
    2019-11-14
    1
    2
  • 余文郁
    function Foo() {

      getName = function() {

        console.log(1);

      }

      return this;

    }

    Foo.getName = function() {

      console.log(2);

    }

    Foo.prototype.getName = function() {

      console.log(3);

    }

    var getName = function() {

      console.log(4);

    }

    function getName() {

      console.log(5);

    }

    Foo.getName();

    getName();

    Foo().getName();

    getName();

    new Foo.getName();

    new Foo().getName();

    new new Foo().getName();
    老师,我做了一道网上的题目,发现做不出来,运行后,发现在node环境会报错,浏览器环境会依次输出2 4 1 1 2 3 3,老师可以帮我解释一下吗,确实有点懵了

    作者回复: 按浏览器上的执行效果理解就对了。

    NodeJS加载的文件是运行在一个模块中,因此function Foo()的代码中的"return this;"并不能得到global,从而导致“Foo().getName();”这一行不能得到global.getName出错。

    2019-11-12
    2
    2
  • 翅膀
    第n+1次,学js. 这次要坚持住

    作者回复: 加油!

    2019-11-12
    2
  • Jack Q
    掌控代码,而不是被代码掌控。

    作者回复: ^^.

    完全赞同楼上观点

    2019-11-11
    2
  • 一步
    JS这门语言成也灵活,败也灵活
    熟练的怎么写怎么舒服,不熟悉的人感觉没有规范太灵活了容易出错

    希望通过这个专栏形成语言的体系
    2019-11-11
    2
  • 潇潇雨歇
    上个月就在期待了,看了课程预告那会
    2019-11-11
    2
  • 勿闻轩外香
    今天立flag,没事儿的时候盘一盘 :)
    2019-11-11
    2
  • lunar
    小岳岳不仅会说相声,js还这么好?😱😱
    2019-11-24
    1
  • 余文郁
    老师,今天突然想到一个问题,就是为什么js中有高阶函数这个东西,可以把函数当参数,还可以返回一个函数,其他语言里没有,这跟js诞生有什么联系吗

    作者回复: 函数式语言特性并不是js独有的,它是一种被广泛认可的语言特性。但在函数式特性方面,Eich没有太强调他在早期语言设计中受到何种影响。

    现在的tc39中的成员们,从整体趋势上来看,是更认可js中的函数式特性,而否定其中的oop特性的。
    所以,有时候感觉这门语言(的特性)已经开始变得怪怪的了。:(

    2019-11-20
    1
  • 鸡蛋火腿酥饼
    老师您好,我现在正在一家公司实习,使用JS为公司开发功能需求的外部库,但是总觉得自己的代码风格和效率差,不知从哪学起,也不知学您这个适合吗?

    作者回复: 如果是这个目的,那么不太适合。因为这个课程的内容,讲工程应用的较少,对代码风格也缺乏讨论。

    这个课程更多的是构建语言的学习与认知的体系,而不是提供应用开发的技能,二者目的不太相同。

    2019-11-14
    1
  • 翰弟
    早闻其名,以为老师曾已经输出过那么多,以为这次课可能没那么多真知,听了开篇词我先保证学完这个课。
    另外发现技术科程的订阅量和得到之类的课不同比。我决定让女票也看这开篇词,接收“新”东西。
    我是一个好不纯粹的程序员
    2019-11-14
    1
  • T T
    对于一个0基础的小白从何入手才能进入这个大前端行业!

    作者回复: 写一个项目,或者重构一个项目。从实际工作下手,是最有效果的。

    另外,你的头像超亲切。呵呵,我曾用这个图做桌面约一两年~ :)

    2019-11-14
    1
  • 高飞
    一直是爱民老师粉丝,支持
    2019-11-12
    1
  • JustinLiu
    原来你是这样的JavaScript。
    2019-11-12
    1
  • EEEEEEEarly
    666
    2019-11-11
    1
收起评论
40
28
返回
顶部