不知道什么时候软件研发工作才开始有了比较严格的“后端”、“前端”、“测试”之类的划分。当然,对项目的推进而言,这种精细化的分工合作不仅非常有利于整体工程的效率,还能提高软件交付的质量,从资源的有效利用率上讲,这种工作分配机制也是极为科学的,我不否认。
只是,在后端研发的岗位做了一段时间并逐渐熟悉了开发规章后(大约一年左右),我发现我只是熟悉了我手上的活儿,而对整个研发链、整个项目的理解还是有点“一叶障目,不见泰山”。我的下游到底做了什么?他们是怎么解决问题的?跟我有什么异同?我非常感兴趣。
举个例子,我曾负责实现项目中的日志收集功能。具体来讲,是由用户选择若干收集项,触发后,由服务器处理相关信息,并把对应的日志文件传递给浏览器,用户得以轻松、一键下载该日志。我们开发的流程是:(此处暂不考虑前后端并行开发)
首先,后端研发人员负责定义接口,并实现服务器的逻辑处理,后端将工作交付给前端;
其次,前端负责实现呈现给用户的、浏览器端的交互逻辑,例如如何添加收集项,如何修改收集项,如何显示收集项弹窗等等;
最后,前后端连调无误后,功能交付给测试。测试团队负责把最后一道关,将功能尽可能无死角的验证。
我的问题是:我们每天都在挥舞着手上的鼠标点击各种各样的按钮,用以完成不同的任务,这是怎么实现的?为什么不会乱套?
换句话说,前端到底是如何把如此复杂、多样的动态交互功能实现的呢?
我发现很多人读书的时候并不看目录。我不这样,我是个会把序言、前言和目录老老实实读完的家伙。要不要通读本书?我就是通过它的序言、前言和目录来做初步的判断。
本书由Rey Bango
作序,你不知道这个人,正如我不知道这个人一样,但这并不妨碍我们去读这篇感情充沛的《序》。
一开头,他就说“20 多年的职业生涯,我也长出了白头发”,然后回首往事,他发现对他影响最大的技术就是 JavaScript。接着夸赞本书的作者Nicholas C.Zakas
为“巨星和导师级的人物”。尔后指出,现在(约成文于2010年前后)的许多技术书籍要么太艰深、晦涩,感觉“好像是要使用 JavaScript 开发导弹制导系统”,要么就是啰哩啰嗦,讲了太多无关知识。而本书就太好了,“细致周到,实实在在,亲切自然,而又深入浅出,是一本写给’普通人’的书,是一本让’普通人’也能写出引以为荣的代码,也能构建令人叫绝的网站的书”。
我真的极佩服这个人,这个人,太会说话了。即便中美文化不同,即便我仅仅看了这五六百字的文章,还是翻译后的,但这些都丝毫无法掩盖序作者的机智和自信,他高超的谈吐、情商已经跃然纸上了。
一般来说,前言、目录都是对整本书框架的概述,里面会包含作者“架构”本书时的线索和逻辑,不太会有很多烧脑或者特别细碎的知识内容。本书前言中最让我感兴趣的是关于 JavaScript 历史的记录。
JavaScript 由Netscape
公司开发,最初的目的是为了解决:在那个网速非常之慢的年代,验证操作费时费力,非常影响用户心情。
为了赶工期,Netscape 与 Sun 合作(Java 即由 Sun 公司研发而来),在各种妥协下,JavaScript 的语法和编程风格都与 Java 相似,甚至连名字都尽可能的相似,但也仅仅是相似而已,Java 和 JavaScript 根本没有什么关系,说 JavaScript 仅仅是在外观上模仿 Java,应该不会有争议。
1993 年,第一个浏览器诞生在美国的一个超算中心,该浏览器名字为Mosaic
;
1994 年,该浏览器的核心人物成立商业公司 - - Netscape,并重写 Mosaic 代码,推广商用,后大获成功。
1995 年,Netscape 决定实现一种全新的浏览器脚本语言,用以在浏览器端解决表单的验证问题。详情见 链接。
1995 年,微软担心浏览器会威胁到自己的操作系统市场,遂买下 Mosaic 授权,并在此基础上开发了 IE 浏览器,捆绑在 Windows 操作系统上发售。
1998 年,Netscape 在与微软的竞争中处于劣势,于是,开放源代码,软件免费,成立 Mozilla 基金会。(Mozilla = Mosaic killer)
如今,Netscape 已经风光不再,甚至当年跟他一样叱诧风云的 IE 浏览器在新一代 Microsoft Edge 浏览器的加持下,依旧没能挽回其颓势,后来者 Google Chrome 和 Safari 成为市场新秀。
我很喜欢“浏览器大战”的这段历史,当然,我也很喜欢 Sun 公司的历史,对比中国,我也很喜欢早期巨人集团、爱多VCD的历史。这些企业里,每一家都在某一个时间点取得了不可思议的商业成就,尔后又因为各种各样内部的、外部的因素逐渐逐渐走向没落,甚至走向灭亡,让人无比唏嘘。
眼见他起高楼,眼见他宴宾客,眼见他楼塌了。这不是看笑话的心态,事实上,直到现在,仍然有很多人对 Netscape,对 Sun 公司致以非常崇高的敬意。我没有看笑话的心态,我只是认为,当一家公司,不惜血本、不计代价的,在一个错误的道路上狂奔时,真是太可怕了。
虽然 Netscape 消失在历史的长河里,但作为 Netscape 最具创造力、最具影响力的发明 - - JavaScript 却顽强的生存下来,积极踊跃的活跃在各个平台 - - Web 端,mobile 端,甚至是服务器端。
不知道大家是如何学习一门计算机语言的?据说通过学习的方式就可以看出“段位”哦。
一年多前,我学习 Golang 那会儿,是去网络上找各种免费的中文教学视频。
工作了几个月后,需要学习的东西逐渐越来越多,时间也渐渐不够用了,晚上到家九点多,看不了一会书,上下眼皮就开始打架。逐渐逐渐,我感觉到视频教学的方式效率实在是太低了。因此后来再看 gRPC 相关知识的时候,我就直接去找官方文档了,大都是英文的,很难很恶心,硬着头皮一个单词一个单词的读。
本次读 《JavaScript 高级程序设计·第三版》这样大部头的书籍,七八百页,跟字典那么厚,是第一次。怎么读?上愁不?说实话,没有捷径可走,一点一点的读呗,发愁又解决不了问题。
JavaScript 的入门并不难,就像其他常见的编程语言一样,首先无非就是 if…else、for 循环、声明变量、定义方法、错误处理这些基本的语法知识,都大同小异,没有什么很特别的地方。
JavaScript 里第一个让我觉得有意思的点是它的变量。如果习惯了 Python 你可能会觉得这没什么,但我仅有 Go 和 一点点 Java 这样静态的、强类型编程语言的开发经验,我就觉得无比的惊奇。一个变量名,时而存储字符串,时而存储数值,时而存储布尔值,不出任何问题,甚至在数组中,每个元素的类型也没有限制。我之前从没有过这样“自由”的编程体验:
曾经有一个后端同事跟我说他虽然懂 JavaScript 语法,但每当看前端的项目代码时,感觉自己学的是假的 JavaScript 语法。我当时哈哈一笑,没能讲出个所以然来,现在我大概知道原因了:他没弄懂 JS 里的面向对象。
面向对象是第二个让我觉得 JavaScript 很有意思的原因,它的设计非常的与众不同。
我们所认为的“传统的、地道的”面向对象首先要有类,“类”就相当于“图纸”,里面定义好你要描述的事物所具有的属性和方法;接着,通过这“图纸”可以创建出任意多个具有相同属性和方法的“实体”,我们称这“实体”为“对象”。
★★★ JavaScript 面向对象的与众不同,首先就体现在对“对象”的定义上。别人有属性
和方法
之分,JS 却并不拘泥这些,全部定性为名值对
了事。我理解的 JS 的对象,跟 Java 中的 map 数据类型差不多,你看:
var person = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName: function() {
alert(this.name);
}
};
★★★ JavaScript 面向对象的与众不同,也体现在创建对象的方式上。除去通过 Object 构造函数和对象字面量来创建单一对象外,还有 名字很高端实际就那样 的“工厂模式”,这些方式并没有什么,Java 里很常见,最让我赞叹的,是它的“构造函数模式”,你看:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer")
var person2 = new Person("Haiyung", 24, "Software Engineer")
一个由 new 操作符调用的普通函数,就生成了一个对象。可是问题在于,函数本身就是一个对象了,是 Function 引用类型的一个对象,这就相当于 new 操作符调用一个对象,结果生成了另一个对象,这让我非常费解。不过我没有追究下去,反正,喏,这就是构造函数:
★★★ JavaScript 面向对象的与众不同,还体现在依靠原型链来实现继承。许多面向对象语言都支持两种继承方式:➀接口继承➁实现继承。接口继承只继承方法签名,但 JavaScript 里面,方法的签名(参数)被数组化,无法实现接口签名,因此 JS 只支持实现继承
,并且,主要是依靠原型链
来实现继承。
我们需要先弄清楚什么是“原型”,才有可能去打“原型链”的主意。
不太严谨的讲,当原型碰到构造函数时才有意义。每一个构造函数都有一个 prototype(原型)属性,这个属性的值是一个对象(原型对象),假设这个对象为 A。使用 new 操作符后跟构造函数名即可创建一个对象,该对象的原型对象就是 A。
再不太严谨的讲,构造函数就好像是“类”,构造函数中的 prototype 属性就像是“类的继承”,通过构造函数创建的对象需要知道两件事:
constructor
属性。__proto__
属性。你能理出构造函数、原型和对象的关系了吗?
那么,假如我们让原型对象等于另一个类型的实例,结果会怎么样呢?
function SuperType() {
this.property = true;
}
function SubType() {
this.subproperty = false;
}
// SubType 要发功开始继承啦...
SubType.prototype = new SuperType();
var instance = new SubType();
alert(instance.property);
两个构造函数,各有一个属性。我们给 SubType 换了一个原型对象,这个新原型就是 SuperType 的实例,结果是原来存在于 SuperType 对象中所有的属性、方法,现在可以在 SubType 实例中调用,这,就是继承了。
JavaScript 中继承的原型链指的是什么呢?一个构造函数的原型指向另一个类型的实例,若另一个类型的实例的原型又指向另另一个类型的实例,如此层层递进下去,就构成了实例与原型的链条,这就是所谓的原型链。
蛮抽象,也蛮有意思。本书的第 6 章就着重讲了 JavaScript 的面向对象程序设计,我看了三四遍才刚能捋清了作者的思路,可见天资之差呀 :(
读这样大部头、有权威、值得信赖、且一版再版的书籍,有好多好处,其中最重要的一点,就是知识系统化。
像stackoverflow
、CSDN
、博客园
这样的技术问答网站,有很多问题的解答方案,但你就是不知道这个答案是从哪里得到的。酷壳网作者左耳朵耗子(陈皓老师)所说的:回到知识的源头去。也许就是这个意思吧。
多读书,多读经典的书,是一个非常非常有意思的体验,往往每走两步,就有一点小福利,再走两步,就有一个惊喜。有的时候,有的章节,如果你刨根问底,还要反复的重读,你可能气急败坏,可能云里雾里,一旦领悟了,那种开心,是刷多少部剧都无法比拟的,那是挑战心智的乐趣。