w3ctech 2011 JavaScript 专题会议(广州站)日前在华师大附中召开,参会者近 300 人,来自国内技术社区的四位知名专家陈广琛、赵劼、周爱民、贺师俊分别做了精彩的演讲,涉及的内容包括云端 NodeJS、JS 异步解决方案 Jscex、开源 Javascript 引擎 Narcissus、ECMAScript 5 的 strict 模式等。InfoQ 中文站整理了大会的精彩内容,供读者参考。
云端 JavaScript 漫游指南
雅虎前端工程师陈广琛演讲的主题是《云端JavaScript 漫游指南》,他以丰富的实例和现场演示介绍了 NodeJS 的强大功能和云端部署的知识。
正如陈广琛在开场白里所说,十年前的 Javascript 还要看 VBScript、PHP、CGI 的脸色,而如今 Javascript 的强大从前端延伸到了后端。在解释 JavsScript 依靠 NodeJS 平台作为服务器端编程语言的优势时,他在会场演示了两个功能不大但让人印象深刻的 NodeJS 开发案例,这些以前 Web 开发人员需要采用其他语言实现的功能,如今用熟悉的 JavaScript 即可完成。让我们来体会一下 NodeJS 的魅力。
域名重定向(biz-to-me)代码示例:
const http = require(‘http’);
var server = http.createServer(function(request, response) {
var host = request.headers[‘host’];
var url = request.url;console.log(‘request from: http://’ + host + url);
host = host.replace(/catchen\.biz$/, ‘catchen.me’); if (host == request.headers[‘host’]) {
host = ‘catchen.me’;
url = ‘/’
}var location = ‘http://’ + host + url;
console.log('redirect to: ’ + location);
response.writeHead(302, {
Location: location
}); response.write('Temporarily moved to ’ + location + ‘.’);response.end();
});
var port = process.env.PORT || 3000; server.listen(port, function(){console.log("Listening on " + port);
});
短 URL 解析(traceurl)的代码示例可以从这里查看。
从这两个例子中,我们可以看到一些亮点,比如:
- 导入函数库时,可以赋值给命名常量,便于范围管理,像 const http = require(‘http’)。
- 服务器端处理主要函数是 createServer 中传入的回调函数 function(request, response)。
- 从 request 解析 http 请求,用 response 返回响应。
- 采用 Javascript 语言,参数 Json 风格。
- 无需配置 Apache。
- 支持 URL 路由(字符串定义和正则表达式两种)。
陈广琛特别介绍了 NodeJS 的 Express.js 库,常用的功能包括:
- 日志管理
- 路由
- cookie 解析
- session 管理
- 模板引擎
有志于从事 NodeJS 应用开发的朋友,可能会担心 NodeJS 相关的支持工具包(package)不够多从而导致开发比较麻烦。陈广琛建议大家利用 NPM 搜索已有的工具包。NPM 是针对 NodeJS 的包管理器,可以用来安装和发布 NodeJS 应用,它能够管理依赖等。除了利用第三方的工具包,陈广琛还介绍了如何构建自己的 package(见短 URL 解析代码示例),大体分为三步:
- 使用 module.exports 编写模块。
- 提供 package.json 和 index.js 文件。
- 使用 npm publish 发布。
演讲的后半部分转到了演讲的关键字——云端。对于已经构建好的 NodeJS 应用,部署在何处?陈广琛指出,无论是租用机房的服务器还是购买 VPS 服务,都不是理想的选择,“云端”才是大势所趋。他介绍了四款 NodeJS 云端服务:
- Heroku
- Joyent no.de( InfoQ 相关报道)
- CloudFoundry
- Nodester
其中 Heroku 提供每月 750 小时的单进程免费服务,适合于简单的 NodeJS 应用和学习实践。
最后,陈广琛指出 NodeJS 的最大优势在于高并发和异步 IO,只有应用存在这些需求时,NodeJS 才会表现出相比其他平台或语言的过人之处。
提升 JavaScript 生产力的“异样”编程手段
IBM 高级咨询师、InfoQ 中文站编辑赵劼以《提升JavaScript 生产力的“异样”编程手段》为题介绍了其创建的Javascript 开源项目 Jscex ,对深陷异步编程困扰的开发人员很有启发和帮助。
老赵在开场阶段一如既往地批评 Java 语言的不足,他以构建书籍索引为例,C#语言的实现代码如下:
// C#
Listkeywords = …;
var result = keywords
.GroupBy(k => k[0].ToUpper())
.ToDictionary(
g => g.Key,
g => g.OrderBy(k => k).ToList());
与此形成鲜明对比的是 Java 语言的实现代码:
List
keywords = …;
Map<Character, List> result = new HashMap<…>();
for (String k: keywords) {
char firstChar = k.charAt(0);
if (!result.containsKey(firstChar)) {
result.put(firstChar, new ArrayList());
}
result.get(firstChar).add(k);
}
for (Listlist: result.values()) {
Collections.sort(list);
}
老赵总结了 Java 的四点不足:
- 命令式编程(强调怎么做)
- 复杂的匿名类型语法
- 强制写清所有类型名
- 无法扩展既有类型
而现代语言的常见特性是什么呢?
- 声明式编程(做什么)
- 易用的 Lambda 表达式语法
- 类型推断(对于静态语言)
- 无侵入的类型扩展
老赵指出,Javascript 有着优秀的特性,不过在异步编程时存在不足,会破坏代码局部性,将逻辑拆分地支离破碎,同时对异步操作之间的协作和组合、异常处理及取消造成了困难,开源项目 Jscex(JavaScript Computation EXpression)正是为了解决这些问题,其借鉴了 F#的计算表达式特性,Jscex 是 Javascript 语言扩展,通过非常巧妙的手段让开发人员享受异步编程的乐趣。比如,在定义异步操作时,需要采用如下代码形式:
// 使用异步构造器执行编译后的代码
var somethingAsync = eval(Jscex.compile(“async”,
function (…) {
// 实现
}
));
调用形式如下:
function () {
var res = $await();
}
适用的异步任务包括:HTTP 请求、UI 事件、时钟回调、查询响应、Web Service 响应、代理消息等。这种编程方式使得开发人员在异步处理时不会被无处不在的 SetTimeout() 函数困扰,确保代码结构清晰、便于维护。
老赵特别介绍了其 Jsces 编译器所采用的核心思想和技术:
- 视 JavaScript 代码为 DSL
- 使用函数的 toString 方法获得代码
- 使用 eval 动态执行代码
关键思路可以概括为:
var compile = function (f) {
// 获得函数代码
var code = f.toString();
// 解析代码至语法树
var ast = parse(code);
// 生成新代码
return generateCode(ast);
}
其优点包括:
- 载体即为普通 JS 代码,行为一致
- 无需额外编译步骤
- 可以使用原有 JavaScript 编辑环境
针对 eval 的性能和安全问题,老赵指出 JScex 支持在发布前生成编译后的代码,去除 eval 和 compile 的开销,解除与编译器的依赖。
目前社区中存在多种异步框架和异步语言,老赵在对比分析时表示,Jscex 的优势在于:
- 使用 JavaScript 表达逻辑
- 极高的灵活度和表达能力
- 只需少量学习
- 完全使用 JavaScript 语法
- 完全保留 JavaScript 语义
- 完全保留 JavaScript 编程体验
Jscex 基于 BSD 协议开源,目前托管于 github 和 sndacode 上。感兴趣的读者朋友可以阅读老赵为 InfoQ 中文站独家撰写的深度技术文章《使用Jscex 改善JavaScript 异步编程体验》。
JS in JS——在 JS 中实现 JS 引擎的详细剖析
资深技术专家、支付宝架构师周爱民分享了Mozilla 开源Javascript 引擎 Narcissus (采用 Javascript 实现)在语法分析、语句执行方面的技术细节,让到场的开发人员对 Javascript 有了更深的理解。
周爱民首先抛出了三个例子,让大家判断一下运行结果分别是什么(读者可以尝试一下):
function() {
}()function() {
}(1)(function() {
})(1)
在强调了理解 Javascript 语法的重要性之后,周爱民介绍了 Narcissus 项目的基本情况,它由 js.js、jsdefs.js、jsparse.js 和 jsexec.js 四个文件组成。其中重点是后两个文件。jsparse.js 主要用于语法分析。在 Narcissus 中,语法层次由高到低分为 Script、Statements、Statement、ParenExpression、Expression 等,都视为 Node。以 var a, i = 100 , v = i + 100; 为例,其语法树为:
jsexec.js 文件主要包含了语句执行的引擎代码,周爱民介绍了 Javascript 语言上下文执行环境、new、with、function、object、eval 等重要概念、技术的实现细节和对开发者的启示。以 new 为例,其中的关键代码如下:
v = f.__construct__(a, x);
……
FOp.__construct__ = function(a,x) {
var o = {}, p = this.prototype;
o.__proto__ = p;
var v = this.__call__(o, a, x);
if (isObject(v)) return v;
return o;
周爱民建议大家认真读一下 Narcissus 项目的源代码,有助于体会 Javascript 的精髓。jsparse.js 和 jsexec.js 两个文件的代码都在 1000 行左右,感兴趣的读者可以结合周爱民的视频学习 Narcissus 项目,这是一个很好的起点。
ECMAScript 5——Improve the Safety of JavaScript
盛大创新院研究员贺师俊在第四场演讲中以 ECMAScript 5 为主题精彩收尾。他首先指出了 ECMAScript 的发展方向,包括:
- API 扩展和标准化:JSON、Array.protoype.forEach/map/filter…
- 通用化,可实现平台对象:get/set accessor、Object.defineProperty 等等
- 适应于 PITL(programming-in-the-large)
他认为 Javascript 传统上是小型开发语言,存在一些不足:
- 设计为一门依赖于 host 环境的脚本语言
- 无内置 module/namespace
- 缺少较全面的标准 API 库
- 缺乏各种 invariants 约束的能力
- 残缺的 OO
正式因为存在这些缺陷,导致开发人员在使用 Javascript 编程时,经常掉进危险的陷阱。贺师俊结合日常工作中的亲身实践列举了几个,包括 this 引用、with 语句等,都会引起潜在的代码漏洞,在企业级开发中,由于代码结构比较复杂,使得开发人员在调试 bug 时难以定位。比如下面这个小例子:
Dog.prototype.setName = function(name) {
this.name = String(name).toLowerCase()
}
贺师俊认为 String(name) 并不是一种鲁棒性的实践方式,反而可能在开发人员的不经意间导致代码的错误而且不易发现,比如:
var q = new Dog()
q.setName(q) // q.setName(‘q’)
如何解决这些问题呢?贺师俊建议开发人员在条件允许的情况下开启 ECMAScript 5 的 strict 模式,并应用一些辅助开发工具包,例如 guard.js 、 jsguards 、 jsHelpers Overload 、 Trademark/Guard proposal 等。
没有参会的朋友可以通过主办方 w3ctech 的相关页面下载幻灯片和观看演讲视频。JavaScript 专题会议北京站和上海站分别将在 8 月 27 日和 9 月 24 日举行,感兴趣的读者可以报名(北京)和预约(上海)参加。InfoQ 中文站将继续关注国内 Web 技术社区的发展。
评论