说明:《JavaScript高级程序设计(第2版)》(预计2010年7月份上市)的审校者谢廷晟针对书中一句关键的表述,给出了如下分析说明。虽然译者也同样意识到将this关键字函数执行时所处的作用域简单地等同起来不恰当,但在书中其他章节里,还有多处类似表述。本着不擅自修改原文的原则,谨以此说明帮助读者慎思明辨(书中也通过译者注形式给出了此文的链接)。感谢廷晟的认真审校。

第5章中有这样一句话:“this是函数在执行时所处的作用域”(《JavaScript高级程序设计(第2版)》第5章5.5.4节正文倒数第3段中)。我觉得作者的这种说法大有问题。对JavaScript不熟悉的读者会越看越糊涂。这里首先需要明确两个概念:函数执行时所处的作用域、在哪个作用域中调用函数函数调用发生的作用域,否则讨论就无法继续深入。把后一概念明确为“函数调用语句所处的那个作用域”应该没有问题。而前一个概念,实际上就是函数的定义所处的那个作用域。以下面的代码为例:


function a() {
 // ...
}

function b() {
 /// ...

 return function c() {
  // ...
 };
}

var d = b();
a();
d();

在这里,函数a、b和d(实际上就是c)都是在全局作用域中调用的。a和b执行时所处的作用域都是全局作用域。但是d执行时所处的作用域并不是全局作用域,而是函数b的局部作用域。说到这里,就可以看到“this是函数在执行时所处的作用域”这一说法的不妥了。假如函数c中引用到了this(在本例中,d是直接调用的,所以this指向的是全局对象),那么按作者的说法,c 岂不是直接运行在全局作用域中而不是b的局部作用域中了?再看下述例子:


var greeting = 'Hello from global scope!';

function e() {
 alert(greeting);
 alert(this.greeting);
}

var tom = {
 greeting:'Hello from Tom!'
};
tom.f = e;
tom.f();

这个例子中的this指向的是什么?显然是tom。那么f(即e)执行时所处的作用域是什么?显然是全局作用域。假如f执行时所处的作用域如作者所说为this所指对象的话,那就意味着在本例中f执行时所处的作用域为tom,也就是说在f执行过程中,与其作用域链相对应的那个变量对象链的最前端那个对象是tom,而这就意味着在此时函数体内对名称greeting进行解析时首先遇到的是tom中定义的greeting,于是两条输出语句的结果都应该是“Hello from Tom!”,这不符合事实,所以按作者的说法所做的那个假设是错误的。

对于this这个关键字,我认为不应该扯什么作用域的事儿,只要向读者说明以下几项这样一句话就够了:函数作为哪个对象的方法调用,函数体内的this(不包括嵌套定义在其中的函数中的this)指向的就是那个对象。直接调用一个函数,相当于把它当作全局对象的方法调用。JavaScript 中没有类作用域的概念,因此方法内部要访问据以调用此方法的那个对象的属性,必须使用this关键字,按‘this.属性名’的语法来访问

  1. 函数作为哪个对象的方法调用,函数体内的this(不包括嵌套定义在其中的函数中的this)指向的就是那个对象。
  2. 结合new运算符调用一个构造函数时,系统会先自动生成一个对象,然后在该对象上调用构造函数。此时在构造函数体内,this指向的就是这个对象。
  3. 直接调用一个函数,相当于把它当作全局对象的方法调用。
  4. JavaScript中没有类作用域的概念,因此方法内部要访问据以调用此方法的那个对象的属性,必须使用this关键字,按“this.属性名”的语法来访问。

与这个问题相关的还有一个函数体内的名称解析的问题。我看过的JavaScript教材上都说得不太全面。实际上,那种直接引用的名称,其名称解析是在作用域链上进行的;而那种按“obj.属性名”方式引用的名称,其名称解析是在obj的原型对象链上进行的(首先检查obj是否直接定义了同名属性,如果没有,则在其原型对象链上逐层查找)。理解了这一点,就更能搞清前面的this与作用域的瓜葛。

谢廷晟,《JavaScript设计模式》和《深入浅出HTML》的译者。

《JavaScript设计模式》    《深入浅出HTML》

眼下,我正在翻译Beginning Android 2(Apress,March 2010)这本书。之所以翻译这本书,一来是因为这本书比较急,而全书又有接近400页的内容需要翻译,如果找其他译者,少说得3个月;而我打算在1个月左右搞定。二来也是为了学习一下Android开发,以后审稿子也可以做到“胸有成竹”。

之所以想到公开征寻技术审稿人,一是上一本书的样章吸引了120多位朋友的热情参与(“经典名著,精选样章”),几位热心的朋友在出版前也为我指出了一些问题,而这些问题在出版前都得到了妥善解决,保证了最终出书的质量;二是在今天这个开放的环境下,如果还延续那种一个人关起门来翻译的模式,不仅会显得译者自己缺乏公开的勇气,更会拖延译稿中问题的解决(译者无法解决书中全部问题很正常),影响出书进度。况且,样章早晚都是要放出来给潜在读者先睹为快的,后放不如早放,这样也有利于潜在读者提前了解这本书的价值所在和翻译质量——“先尝后买”嘛。

当然,征寻技术审稿人的主要目的,还是为了请领域专家来给译稿把关,尽最大努力来消除翻译中存在的错误或问题,确保最终出书的质量。下面就说一说对技术审稿人的要求:

1、对Android开发有浓厚的兴趣和一定的开发经验;
2、愿意花时间“先睹为快”并有能力指出错误和问题;
3、有一定的中文文字表达能力,能够看懂英文原文。

有意参与这本书技术审校的朋友,请给我发邮件(lsf.email[at]gmail.com)吧,邮件标题请填“Beginning Android 2审校”(以便过滤归类)。

声明一下:对所有参与审校的朋友,我会在译者序中具名致谢。对参与审校而且指出问题较多的朋友,届时将赠送样书(样书可以是本书中文版,或者我翻译过的其他图书,或者图灵公司出版的其他图书——届时我们可以再商量)

另外,对于只是想“先睹为快”的朋友,也可以给我发邮件,邮件标题请填“Beginning Android 2试读”,我会给大家共享部分样章。

期待Android开发专家、高手、大牛、爱好者,伸出援手、不吝赐教!让我们共同携手,为Android开发社区和爱好者又快又好地奉献一本优秀的引进版图书。

Beginning Android 2

Beginning Android 2

配置完Android开发环境后,遇到两个问题,一个属于非技术问题,另一个属于技术问题。

先说非技术问题。

很简单,启动Android模拟器(需要先创建AVD)时,先看到的是一个文本界面,我一开始以为自己的配置出了什么问题。迷惑了大半天,晚上从外面吃饭回来,突然想起来《Android基础教程》(人民邮电出版社,2009年11月)中有一段提示:“启动模拟器需要花较长时间。可以这样想象一下——首次开机时,手机也需要启动,就像任何计算机系统一样。关闭模拟器就像是关闭手机或取出手机电池一样。”会不会是我太着急了?应该有点耐心才好。于是,我重新启动模拟器,耐心等待……大约3分钟后,终于看到Android的图形用户界面,OK。

正好《Beginning Android 2》这本书中也有一段相关的话:NOTE: The first time you use an AVD with the emulator, it will take substantially longer to start than it will subsequent times.(注意:第一次使用AVD来启动模拟器的时间会比较长,后续的启动速度会有所提升。)

再说技术问题。

前面只是解决了启动模拟器的问题,接下来就是要在模拟器中实际地加载新应用程序并进行测试。但是,我新创建了FirstApp应用程序,在通过Eclipse运行该项目时(也可以在命令行中使用ant构建项目,然后运行android命令,再启动模拟器;不过,这需要再下载其他软件包),提示出错,错误信息如下:

1. Project “FirstApp” is missing required source folder: ‘gen’
2. The project could not be built until buid path errors are resolved.

在网上搜索到几个解决方案(列在下面,供朋友们参考)。但奇怪的是,在刚搜索到第一个方案时,还没等到采取任何措施,Eclipse中的错误居然自动消失了(FirstApp项目下方的红叉也不见了),再Run as Android Application,一切正常了。我想,也许正如第三个方案中某人所说的,Eclipse并不能实时检测到OS文件系统的变化(编译项目时,会生成新文件),这也许就是导致这个技术问题的原因——至于是不是这个原因,还有待于进一步求证。

一、右击项目,选择preferences->builder,在右边的configure一栏中将Android Packege Builder一项提到Java Builer之前
出处:http://www.androidin.net/bbs/thread-708-11-1.html

二、将Eclipse自动生成的R.java删掉,刷新项目,R.java便会重新生成
出处:http://www.blogjava.net/crazycoding/archive/2010/03/27/316701.html

三、在项目文件夹中新创建一个Java类或者直接修改自动生成的类文件
出处:http://www.coderanch.com/t/466092/Android/Mobile/android-eclipse

以下是几个人的回复,感觉这种讨论的技术氛围很不错。今天太晚了,明天天亮还要去平谷,回来再翻译。

James Dixon的回复
Hi Divya
I’ve had the same problem as well. I think the issue is that the project creation does not initiate a build when it finishes, so you need to make a change, and save for it to generate the gen folder.
For me creating a new java class seemed to do the trick, but I’d imagine just making a change to a file and saving should work too.

Robert F. Howard的回复
I just ran into this, too. I am following the example in Hello Android, which I assume is what the others in this thread were doing. James’s solution (editing the source file) worked for me, so thank you for that.
So your solution is good, but I don’t think I totally believe the diagnosis. The thing is, the directory actually did exist before I edited the file and rebuilt. This is my first time using Eclipse, and it’s very disappointing. The error message should specify the full path of the directory it wants, and then it should be possible to create the directory and re-build, but it doesn’t work until the source file is edited. It makes me wonder what is really going on inside Eclipse.

Tim Holloway的回复
This seems to be a small glitch courtesy of Eclipse’s distancing itself from the OS filesystem (which is why Eclipse has an explicit Refresh command).
The gen folder and the “R.java” file are built by one of the Android utilities. The Eclipse Android plugin invokes this app, but it doesn’t always know when it needs to. I have similar problems when I want to define a new resource ID. Since I can’t seem to get the GUI resource ID definer to enable itself, I just create new IDs in the resource files themselves. But unless I trigger the android resource generator, they don’t get inserted into “R.java”.
And you don’t want to manually insert into “R.java”, because when the resource compiler does fire off, your code mods will be overwritten.
One way to force the issue is to select the Project/Clean menu command. If you have the automatic build switched off, you’ll then have to initiate a build. Otherwise the clean will fire off the auto-build process.

在本文写作时,Android SDK的最新版本是2.1。现在,我们来看一看如何在Windows平台下构建Android 2.1开发环境。

先期需要下载的软件包如下:

1、JDK 1.6+
2、Android SDK 1.6
3、Android SDK Setup
4、Eclipse IDE for Java Developers

看到这些,可能心急的朋友会禁不住问:“不是要构建Android 2.1开发环境吗?怎么还要下载Android SDK 1.6而不是2.1呢?”

没错,是要讲怎么构建Android 2.1开发环境。但是,经过几次尝试,我发现直接下载安装Android SDK 2.0和2.1有问题。什么问题?简单地说,就是这两个最新版本的SDK包中都不包含adb.exe文件,无法在Eclipse中指定Android SDK的位置(也就意味着没法使用Eclipse来开发)。因此,这才走了一条曲线救国的道路;也许,正如我自己的尝试所证实的:Android SDK 2.0和2.1实际上都是升级包,而不是完整的开发包。我比较了一下,Android SDK 2.0和2.1的大小分别是76.6MB和77.3MB,而Android SDK 1.6的大小则是248MB,相差还是很悬殊的,这一点似乎也佐证了我的判断。但是,不管怎样,先下载Android SDK 1.6,然后再通过ADT(Android Developer Tools,Android开发人员工具)和Android SDK Setup程序来下载和更新Android SDK 2.0和2.1,是成功了。

闲话少说,言归正传。

首先,访问http://java.sun.com/javase/downloads/widget/jdk6.jsp
下载Java SE Development Kit 6u20(jdk-6u20-windows-i586.exe)
文件大小76.67 MB。

其次,访问http://dl.google.com/android/archives/android-sdk-windows-1.6_r1.zip
下载Android SDK 1.6(android-sdk-windows-1.6_r1.zip)
文件大小248M。

然后,访问http://dl.google.com/android/android-sdk_r04-windows.zip
下载Android SDK Setup(android-sdk_r04-windows.zip)
文件大小22MB。

最后,访问http://www.eclipse.org/downloads/
下载Eclipse IDE for Java Developers(eclipse-java-galileo-SR2-win32.zip)
文件大小92.7MB。

下载完成后,开始安装和配置。

第一步,安装和配置JDK。

下载后,双击运行jdk-6u20-windows-i586.exe,假设选择安装到C:\Java\jdk1.6.0_20目录下(当然,安装到默认路径下也没有问题)。安装完毕后,就是配置环境变量。步骤如下:

(1)设置JAVA路径

在“我的电脑”上点右键,选“属性”,打开“系统属性”对话框,点“高级”选项卡,再点“环境变量”按钮,在打开的对话框中的“系统变量”下方,点“新建”,然后在对话框中的“变量名”中填JAVA_HOME,在“变量值”中填C:\Java\jdk1.6.0_20,点“确定”。

(2)设置CLASS路径

再“新建”一个系统变量,在“变量名”中填CLASSPATH,在“变量值”中填.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar。
说明:最开始的.;中的.(点)表示当前路径,;(分号)是路径分隔符。接下来的%JAVA_HOME%引用的是前面刚创建的JAVA安装路径。

(3)设置PATH路径

PATH变量一般都有了,因此选中点“编辑”,然后在“变量值”后面加上;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin,注意前面的分号。

这样,JDK就安装好。“开始->运行”,输入cmd,然后在命令行提示符中输入:java -version,应该能够看到java version “1.6.0_20″信息;JDK安装成功。

第二步,解压和配置Android SDK 1.6

将下载到的android-sdk-windows-1.6_r1.zip解压缩到C:\android-sdk-windows-1.6_r1目录中(解压到哪个目录都没有问题)。然后,配置环境变量。步骤如下:

(1)设置Android路径

重复第一步的(1),新建一个“系统变量”,在“变量名”中填Android_Home(大小写没有问题),在“变量值”加填C:\android-sdk-windows-1.6_r1。

(2)设置PATH路径

“编辑”PATH变量,在“变量值”后面加上;%Android_Home%\tools,注意前面的分号。

这样,Android SDK 1.6就安装好了。“开始->运行”,输入cmd,然后在命令行提示符中输入:android -help,应该能够看到帮助信息;Android SDK 1.6安装成功。

第三步,解压Eclipse,关联Android SDK,安装ADT

将下载到的eclipse-java-galileo-SR2-win32.zip解压缩到C:\eclipse,然后进入这个文件夹,双击eclipse.exe,启动Eclipse。

安装ADT:菜单“Help -> Install New Software…”,打开Install对话框,点击Add…按钮,添加站点(Add Site),在Name中填ADT,在Location中填https://dl-ssl.google.com/android/eclipse/。然后,下载安装ADT。

关联Adnroid SDK:菜单“Windows->Preferences”,打开Preferences对话框,点击Android,在右侧的Android Reference中,点SDK Location文本框右侧的Browse…按钮,找到C:\android-sdk-windows-1.6_r1,“确定”。

第四步,解压Android SDK Setup,下载更新Android SDK 2.0和2.1

将下载到的android-sdk_r04-windows.zip解压缩到C:\android-sdk-windows,然后进入这个文件夹,双击SDK Setup.exe,启动Android SDK and AVD Manager,选中左侧Settings项,然后在右侧面板选中Force https://… sources to be fetched using http://,然后选择Save & Apply。然后,参见这里的图解:

如何使用Android SDK Setup? http://www.android123.com.cn/zhongwensdk/366.html

我选择了所有需要更新的内容,包括:

  • Android SDK Tools, revision 5
  • Documentation for Android SDK, API 7, revision 1
  • SDK Platform Android 2.1, API 7 revision 1
  • Sapmles for SDK API 7, revision 1
  • SDK Platform Android 2.0.1, API 6, revision 1

耐心等待吧——注意,如果更新过程有提示,可能是因为你正在使用C:\android-sdk-windows-1.6_r1目录,或者杀毒软件不允许改写其中的文件,此时需要退出所有程序或暂时关闭杀毒软件。

一切顺利的话,到此Android 2.1开发环境(或者说,Android 1.6、2.0和2.1的开发环境)就构建好了。

附录:

Android开发包及相关软件下载地址
http://www.android123.com.cn/android_kit.html

鸣谢:http://www.android123.com.cn/

在一年一度的新春佳节即将到来之际,应热心读者的要求,为满足大家先睹为快的愿望,也为了答谢朋友们对本博客长期以来的支持,即日起到春节前夕,本站将发布尚未出版的《JavaScript高级程序设计(第2版)》一书的样章(暂定为3章,约115页)。

申请办法

1、发邮件到:[email protected]
2、邮件主题:《JavaScript高级程序设计(第2版)》样章;邮件内容:您的Email地址。
3、24小时内收到样章,先睹为快!

备注:样章格式为PDF,托管在“Google文件”,可以在线查看(无须登录),也可以下载和打印。希望在线查看PDF的朋友,请在邮件正文中注明“希望接收Google文件”字样,即可收到样章的链接(也可以下载);否则,将收到PDF文件(*请确保有5M以上的空余邮箱空间)
样章列表(详细目录

第3章 基本概念
第4章 变量、作用域及内存问题
第5章 引用类型

《JavaScript高级程序设计(第2版)》简介

本书是人民邮电出版社图灵公司引进出版的大畅销书、JavaScript权威著作《JavaScript高级程序设计》的最新升级版。《JavaScript高级程序设计》自2006年11月出版以来,已经累计销售逾30000册,而且至今仍然十分畅销。这一点可以通过北京新华文化发展有限公司(新华书店)近期的店面销售数据看出来(大家可以自行比较一下其他畅销书的销量)。应该说,在Web 2.0革命爆发的同时,人民邮电出版社图灵公司引进出版的本书成就了计算机图书市场上难得一见的奇迹。

本书作者尼古拉斯·扎卡斯(Nicholas C. Zakas)现为Yahoo!公司首席前端工程师,世界顶级Web技术专家。原书第1版曾被选为Yahoo!公司YUI(Yahoo! User Interface Library,Yahoo!用户界面库)团队的内部培训教材。

2009年初,本书第2版面世(《Professional JavaScript for Web developers, 2nd Edition》)。新版本不仅篇幅由原来的600多页增加到800页,而且几乎全部更新、重写了上一版的内容,删除了上一版中与今天的职业需求无关的主题,新增了大量比上一版更有价值、更能反映JavaScript最新发展成果的内容。从颇具深度的JavaScript语言基础到作用域(链),从JavaScript引用类型到面向对象编程的最佳实践,从极其灵活的匿名函数到闭包的内部机制,从浏览器对象模型(BOM)到客户端检测,从文档对象模型(DOM)到基于事件的Web脚本编程,从错误处理到前端调试,从XML(E4X)到Ajax及JSON,从高级前端开发技术到前沿的客户端存储,从最佳编程实践到展望即将成为现实的API,直至JavaScript未来的发展。全书彻底涵盖了JavaScript技术的各个方面,几乎涉及到了Web前端开发的每一处细节。可以预见,这部著作一定会成为Web前端开发人员不可多得的又一部经典。

目前,《JavaScript高级程序设计(第2版)》的翻译工作已经进入后期阶段(全书22章,所剩不到5章)。而且,为确保新版及时上市与读者见面,出版社采取了与译者同步翻译、同步编辑审校的特别措施。新版本预计2010年上半年可以上市;当然,在确保出版品质的前提下一定会尽量往前赶!

样章详细目录

第3章 基本概念 1
3.1 语法 1
3.1.1 区分大小写 1
3.1.2 标识符 1
3.1.3 注释 2
3.1.4 语句 2
3.2 关键字和保留字 3
3.3 变量 4
3.4 数据类型 5
3.4.1 typeof操作符 5
3.4.2 Undefined类型 6
3.4.3 Null类型 7
3.4.4 Boolean类型 7
3.4.5 Number类型 8
3.4.6 String类型 14
3.4.7 Object类型 16
3.5 操作符 17
3.5.1 一元操作符 17
3.5.2 位操作符 20
3.5.3 布尔操作符 26
3.5.4 乘性操作符 29
3.5.5 加性操作符 30
3.5.6 关系操作符 32
3.5.7 相等操作符 34
3.5.8 条件操作符 35
3.5.9 赋值操作符 36
3.5.10 逗号操作符 36
3.6 语句 37
3.6.1 if语句 37
3.6.2 do-while语句 38
3.6.3 while语句 38
3.6.4 for语句 38
3.6.5 for-in语句 40
3.6.6 label语句 40
3.6.7 break和continue语句 41
3.6.8 with语句 42
3.6.9 switch语句 43
3.7 函数 45
3.7.1 理解参数 47
3.7.2 没有重载 48
3.8 小结 49

第4章 变量、作用域和内存问题 1
4.1 基本类型和引用类型的值 1
4.1.1 动态属性 2
4.1.2 复制变量值 3
4.1.3 传递参数 4
4.1.4 检测类型 6
4.2 执行环境及作用域 6
4.2.1 延长作用域链 9
4.2.2 没有块级作用域 10
4.2.3 声明变量 10
4.2.4 查询标识符 11
4.3 垃圾收集 12
4.3.1 标记清除 12
4.3.2 引用计数 13
4.3.3 性能问题 14
4.3.4 管理内存 15
4.4 小结 15

第5章 引用类型 1
5.1 Object类型 1
5.2 Array类型 3
5.2.1 转换方法 6
5.2.2 栈方法 7
5.2.3 队列方法 8
5.2.4 重排序方法 9
5.2.5 操作方法 11
5.3 Date类型 12
5.3.1 继承的方法 14
5.3.2 日期格式化方法 15
5.3.3 日期/时间组件方法 15
5.4 RegExp类型 17
5.4.1 RegExp实例属性 19
5.4.2 RegExp实例方法 19
5.4.3 RegExp构造函数属性 21
5.4.4 模式的局限性 23
5.5 Function类型 23
5.5.1 没有重载(深入理解) 25
5.5.2 函数声明与函数表达式 25
5.5.3 作为值的函数 26
5.5.4 函数内部属性 27
5.5.5 函数属性和方法 29
5.6 基本包装类型 31
5.6.1 Boolean类型 32
5.6.2 Number类型 33
5.6.3 String类型 35
5.7 内置对象 42
5.7.1 Global对象 43
5.7.2 Math对象 46
5.8 小结 49

Original Post:What makes a good browser API?
Nicholas C. Zakas,2009年11月24日
翻译完成:2010年1月22日,最后更新:2010年1月22日

上个月,我又参加了Mozilla公司组织的一次研讨会,这一次讨论的是Web数据库。虽然研讨会的议题很有意思,但我觉得会议期间大家对另一个问题的争论似乎更值得关注。争论中,与会者针对浏览器到底应该为JavaScript提供什么样的API分成两派。一派坚持认为原生的JavaScript API应该尽量保持低级化,然后由库开发者在低级API基础上再去构建更好用的接口。另外一派,也是我所在的阵营,则认为中级API才是大势所趋。没有人认为浏览器应该向开发人员提供高级API。所谓低级、中级、高级到底都是什么意思呢?

低级API

低级API仅为提供基本功能而设计。由于只要能实现相应功能即可,因此这种API不需要很直观或者很好理解。有时候,低级API确实会给初级甚至中级开发人员造成理解上的困难。这样一来,借由人们频繁使用来发现相应API问题的机会就大为减少了。大家都会指望库开发者在这些低级API基础上实现直观、好用的API,以便于普通开发人员使用。doument.cookie就是说明低级API最好的一个例子。

作为JavaScript开发人员操作cookie的唯一接口,document.cookie可谓有史以来最难使用的一个API。关于cookie,我专门写过一篇文章,还探讨过它的安全性问题,其中都涉及到如何在JavaScript中使用它们;因此,这里只能算是一个简单的介绍了。要设置cookie,必须以正确的cookie格式来设置document.cookie属性,例如:

document.cookie = “name=Nicholas; domain=nczonline.net; path=/; expires=Sat, 02 May 2009 23:38:25 GMT

要取得cookie,则需要读取document.cookie,返回的字符串是如下列所示的名值对格式:

name1=value1; name2=value2; name3=value3; name4=value4

而为了得到想要的值,必须先从这个字符串中查找相应的名字,然后再解析出相应的值。

之所以把这种API归类为低级API,是因为其实现要求你必须先了解cookie的内部格式,然后才能使用它。实际上,document.cookie属性只是在简单地模仿Set-Cookie和Cookie这两个对开发人员不可见的HTTP首部。为了写cookie,必须要理解字符串的确切格式,这涉及到其中的名和值必须采用URI编码形式,而其他片段之间必须以一个分号和一个空格来分隔,此外还必须知道设置过期日期的正确日期格式。反过来也一样,在读cookie时,你同样需要知道返回的字符串是什么格式,然后才能从中解析出想要的数据。这就是所谓的“遇繁不简,遇简也不简”。一句话,这种API对于不了解cookie的人根本没有用。

如果大多数开发人员都不会直接使用某个API,你就可以说它是低级API。不用,是因为使用它们所需的知识储备(Cognitive Overhead)太多了。绝大多数开发人员在使用JavaScript读写cookie时,最终都会求诸于一个JavaScript库例如YUI中的Cookie工具(YUI2YUI3),这些工具把那些令人讨厌的实现细节都隐藏起来了。

这正是那些低级API的支持者所愿意看到的:浏览器应该只提供基本功能,而基于这些功能开发易用API的任务应该交给开发人员社区。这些人支持低级API有一个主要的理由,即围绕基本功能可以实现任何层次的抽象,开发人员也会因此获得更多选择,从而更好地利用基本功能。

低级API的问题在于浪费时间。如果你创建了低级API,那结果就是潜在用户的数量会很少。至于什么时候能够出现好用的抽象工具,只能指望某一天这些用户中有(一个或几个)人会意识到确实有必要去做这件事,以便其他社区人员更好地利用该API。如果你想让新API尽快地被别人使用,你就会明白应该怎样去改进它,低级API根本不合适。

提示:大多数服务器端语言(如 ASP.NETJSPPHP)都提供了读写cookie的原生抽象,但JavaScript始终都没有。

高级API

这一争论的另一个极端是高级API。高级API设计出来就是为了让开发人员直接使用的,并且一般都非常直观。这种API不仅要考虑提供某种功能,而且还要提供使用相应功能的友好、易用的接口。高级API设计首先考虑的是开发人员的方便,因而通常需要对开发人员使用API的方式从理论上作出归纳。显然,这又是一个问题:谁能确切地知道某个人希望怎么去使用一个API呢?因此,在浏览器中提供原生的高级API几乎就是一个不可能完成的任务。

各式各样的JavaScript库就是高级API的典型例子。这些库都面向相同的浏览器,但为实现相同功能而提供的接口却差别很大。使用jQuery的方式与使用YUI截然不同;这是件好事,因为开发人员可以选择。可是,如果你告诉YUI开发人员必须使用jQuery语法写代码——因为只能使用一种语法;或者相反,会怎么样呢?相信对此提出抗议的开发人员一定会成群结队。强迫人们必须以某种方式开发是不幸之源。只有抽象,或者说只有随时都可以提高和降低抽象级别,才会让开发充满乐趣,也才能激励开发人员不断地创新。

高级API要求的知识储备非常低,因此开发人员无需了解太多就可以直接使用。但值得高兴的是,没有人认为浏览器应该提供高级AIP。大家都希望有所选择,都希望不同程度的抽象。 查看全文 »

Original Post:What makes a good front end engineer?
Nicholas C. Zakas,2007年8月15日
翻译完成:2010年1月10日,最后更新:2010年1月10日

昨天,我负责了Yahoo!公司组织的一次面试活动,感触颇深的是其中的应聘者提问环节。我得说自己对应聘者们提出的大多数问题都相当失望。我希望听到一些对在Yahoo!工作充满激情的问题。在昨天的应聘者中,只有一个人的问题是我认为最好的,那个人问我:“你觉得怎么才能成为优秀的前端工程师?”我觉得很有必要把这个问题从面试房间里拿出来讨论一下。

首先,前端工程师必须得掌握HTML、CSS和JavaScript。只懂其中一个或两个还不行,你必须对这三门语言都很熟悉。也不是说必须对这三门语言都非常精通,但你至少要能够运用它们完成大多数任务,而无需频繁地寻求别人的帮助。

优秀的前端工程师应该具备快速学习能力。推动Web发展的技术并不是静止不动的,没错吧?我甚至可以说这些技术几乎每天都在变化,如果没有快速学习能力,你就跟不上Web发展的步伐。你必须不断提升自己,不断学习新技术、新模式;仅仅依靠今天的知识无法适应未来。Web的明天与今天必将有天壤之别,而你的工作就是要搞清楚如何通过自己的Web应用程序来体现这种翻天覆地的变化。

计算机科学这个大门类下面的许多分支在人们眼中实际上都不外乎科学。但是,我们所说的前端不是什么科学,而是艺术。艺术家不仅要掌握谋生的技术,还要懂得如何运用。对同一个问题的解决方案在这种情况适用,在另一种情况下可能就不适用。对Web应用程序的前端而言,解决同一问题的方案经常会有很多。没有哪个方案是错的,但其中确实有一些是更合适的。优秀的前端工程师应该知道在什么情况下使用哪种方案更合适,而在什么情况下应该重新选择。

优秀的前端工程师需要具备良好的沟通能力,因为你的工作与很多人的工作息息相关。在任何情况下,前端工程师至少都要满足下列四类客户的需求。

  1. 产品经理——这些是负责策划应用程序的一群人。他们能够想象出怎样通过应用程序来满足用户需求,以及怎样通过他们设计的模式赚到钱(但愿如此)。一般来说,这些人追求的是丰富的功能。
  2. UI设计师——这些人负责应用程序的视觉设计和交互模拟。他们关心的是用户对什么敏感、交互的一贯性以及整体的好用性。他们热衷于流畅靓丽但并不容易实现的用户界面。
  3. 项目经理——这些人负责实际地运行和维护应用程序。项目管理的主要关注点,无外乎正常运行时间(uptime)——应用程序始终正常可用的时间、性能和截止日期。项目经理追求的目标往往是尽量保持事情的简单化,以及不在升级更新时引入新问题。
  4. 最终用户——当然是应用程序的主要消费者。尽管我们不会经常与最终用户打交道,但他们的反馈意见至关重要;没人想用的应用程序毫无价值。最终用户要求最多的就是对个人有用的功能,以及竞争性产品所具备的功能。

那么,前端工程师应该最关注哪些人的意见呢?答案是所有这四类人。优秀的前端工程师必须知道如何平衡这四类人的需求和预期,然后在此基础上拿出最佳解决方案。由于前端工程师处于与这四类人沟通的交汇点上,因此其沟通能力的重要性不言而喻。如果一个非常酷的新功能因为会影响前端性能,必须删繁就简,你怎么跟产品经理解释?再比如,假设某个设计如果不改回原方案可能会给应用程序造成负面影响,你怎么才能说服UI设计师?作为前端工程师,你必须了解每一类人的想法从何而来,必须能拿出所有各方都能接受的解决方案。从某种意义上说,优秀的前端工程师就像是一位大使,需要时刻抱着外交官的心态来应对每一天的工作。

我告诫新来的前端工程师最多的一句话,就是不要在没有作出评估之前就随便接受某项任务。你必须始终记住,一定先搞清楚别人到底想让你干什么,不能简单地接受“这个功能有问题”之类的大概其的说法。而且,你还要确切地知道这个功能或设计的真正意图何在。“加一个按钮”之类的任务并不总意味着你最后会加一个按钮。还可能意味着你会找产品经理,问一问这个按钮有什么用处,然后再找UI设计师一块探讨按钮是不是最佳的交互手段。要成为优秀的前端工程师,这种沟通至关重要。

无论从哪个方面讲,我都觉得前端工程师是计算机科学职业领域中最复杂的一个工种。绝大多数传统的编程思想已经不适用了,为了在多种平台中使用,多种技术都借鉴了大量软科学的知识和理念。成为优秀前端工程师所要具备的专业技术,涉及到广阔而复杂的领域,这些领域又会因为你最终必须服务的各方的介入而变得更加复杂。专业技术可能会引领你进入成为前端工程师的大门,但只有运用该技术创造的应用程序以及你跟他人并肩协同的能力,才会真正让你变得优秀。

延伸阅读

Nicholas C. Zakas的书

Professional JavaScript for Web Developers, 2nd Edition Professional Ajax, 2nd Edition Even Faster Web Sites

Original Post:Surviving an interview with me
Nicholas C. Zakas,2007年3月27日
翻译完成:2010年1月9日,最后更新:2010年1月10日

早就打算写这篇文章了,但时至今日才决定动笔。如果你投了简历,那么应该会在面试你的人名单里找到我的名字。你现在就有点紧张了,(好啦,别不好意思)面试总会让人感觉有点不舒服。作为面试官,我其实并不算难对付,但如果你想在我们谈话之后让我放你过关,你确实得做一些必要的准备。

  • 回答问题。我问你一个问题,你必须要回答它。我遇到应聘者在回答我问题时顾左右而言他的情况太多了。我知道你会有些紧张,说几句不着边际的话可能有助于缓解,但请你不要喋喋不休,要赶快回到正题上来。我不想知道你的宠物猫最近又出了什么新状况,我只想听到你的回答。假如你没有听明白我问的是什么,可以要求我再解释一下,重复几遍问题或者换一种问法,对我而言没有什么。
  • 告诉我你不知道什么。如果我问到了你不知道的问题,一定要告诉我。我不认为你的大脑里可以装得下百科全书。在知道了你不知道什么以后,我对你的评估才会更加公平。问题仍然要回答,但我会给你一些提示,同时也可以考察一下你解决问题的能力。
  • 不要放弃。在我面试你的过程中,不要总想着放弃。如果你被我前面的话不幸言中,那么你可能会面对一个让你不知所措的问题,而且你也告诉我你答不上来了。此时此刻,千万不要打退堂鼓!我会尽力提醒你,让你找到正确答案;因此不要随随便便打断我说:“我真的不知道。”在我们这个行业,你经常会遇到没有现成解决方案的挑战,到时候你会轻易放弃吗?我必须知道你具备解决问题的能力,而不是遇到一点挫折就轻言放弃。
  • 不用担心怪问题。有些公司的确有吓唬应聘者的传统,他们会让你回答一些类似脑筋急转弯似的稀奇古怪的问题。对那种面试方式,我不敢苟同。我提的所有问题都有答案,而且绝大多数还不止有一个正确答案;我保证一个怪问题也不会问你。因为这样既会让你难堪,又对我毫无意义。你大可放心,我的每个问题都至少会有一个正确答案。
  • 自圆其说。如果你提到了某个解决方案或者强调自己掌握了某方面知识,请做好进一步讨论它的准备。假设我问了一个问题,你在回答这个问题时提到:“对,因为IE不支持CSS3……”然后,你最好能够跟我讨论一下要是IE支持CSS3你会怎么办。
  • 不要说自己是专家。大多数面试中可能都需要注意这一条,但我对这一条尤其敏感。我从来不会把应聘者划分为三六九等,因此你也不必告诉我你属于哪个等级。一旦你声明自己已经跻身“专家”的行列,我怕有些问题会让你下不来台。我确实见过自称专家而又确实是专家的人。但是,我认为真正的专家不会自己说出来,而是会做给你看。
  • 不要靠卖弄赚取我的好印象。如果我想知道什么,我会问。我知道在面试时需要了解哪些信息,只要一听到有人说“想不想看一个绝妙的技巧?”或者其他类似的话,我都有一种立即中断面试的冲动。所以,请尽力回答好我的问题即可。
  • 充满激情。如果你想得到跟我一起工作的机会,请给我一个愿意跟你共事的理由。最好的理由就是要有激情,把你主动、积极学习的热情展示出来。希望你能谈一谈产品、公司,以及为什么想得到这份工作。尤其要注意最后一点,我不想听你说你当前的工作如何如何讨厌。当然,可以解释一下为什么现在或者过去没有从事你喜欢的工作,但你一定要告诉我你对自己今后的成长有何打算,还有为什么你应聘的这个职位能够有助于你的成长。

没错,我确实希望将来有可能被我面试的所有人都看到这篇文章。我希望你能在我面试你时表现得非常好,真的,确实如此。说来也简单,只要你留意上述这些常见的问题,并且原原本本地展示你自己就足够了。说不定哪一天,你就会跟我坐到同一间办公室里了。

注意,My Yahoo!团队正在招聘呢。如果你是一位有才华的软件工程师,又对创造价值和Yahoo!公司充满激情,请跟我联系,咱们谈谈。

延伸阅读

Nicholas C. Zakas的书

Professional JavaScript for Web Developers, 2nd Edition Professional Ajax, 2nd Edition Even Faster Web Sites

Original Post:Interviewing the front-end engineer
Nicholas C. Zakas,2010年1月5日
翻译完成:2010年1月7日,最后更新:2010年1月10日

面试前端工程师对我来说是一件非常有意思的事,因为面试过程很大程度上也是自我提升的过程。无论大公司还是小公司,之所以在如何招聘到真正有能力的前端工程师方面会遇到同样的问题,就是因为负责招聘的那些人不知道自己公司需要什么样的人,结果问问题时也问不到点子上。经过这几年在行业里的摸索,我总结出了自己的一套很有效的面试前端工程的方法。

有的应聘者说我不好对付,但留给他们这样的印象也并非我所愿。我觉得之所以他们说我不好对付,主要是因为我问他们问题时问得太细了。以前我曾专门写过一些东西,告诉应聘者怎么才能通过我的面试以及怎样才能成为优秀的前端工程师应该具备什么样的素质,而我的面试可以说完全是按照那两篇文章的标准进行的。我不会问一些特别偏门的问题,也不认为出几道逻辑题就能考出人的真实水平。我唯一的想法就是确定你能否胜任我们要招的这个职位。为此,我需要简单地考察如下几个方面。

基本知识

我们生活在互联网时代,你想知道的任何事情几乎都能在15分钟内找到相关信息。可是,能找到信息并不等于你会使用它。我认为所有前端工程师至少都应该掌握某些基本的知识,才能有效地完成自己的工作。如果一遇到问题,就停下工作上网四处搜索解决方案,怎么可能保证按期完成工作呢?听听,还有谁在说“我不知道,但我可以上网搜到。”请这些同学把手举起来,让大家认识一下(immediately raises a flag for me.)。下面我列出一些基本的知识点,这些都是我认为一名前端工程师(无论工作年头长短)在没有任何外来帮助的情况下就应该知道的。

  • DOM结构——两个节点之间可能存在哪些关系以及如何在节点之间任意移动。
  • DOM操作——怎样添加、移除、移动、复制、创建和查找节点。
  • 事件——怎样使用事件以及IE和DOM事件模型之间存在哪些主要差别。
  • XMLHttpRequest——这是什么、怎样完整地执行一次GET请求、怎样检测错误。
  • 严格模式与混杂模式——如何触发这两种模式,区分它们有何意义。
  • 盒模型——外边距、内边距和边框之间的关系,IE < 8中的盒模型有什么不同。
  • 块级元素与行内元素——怎么用CSS控制它们、它们怎样影响周围的元素以及你觉得应该如何定义它们的样式。
  • 浮动元素——怎么使用它们、它们有什么问题以及怎么解决这些问题。
  • HTML与XHTML——二者有什么区别,你觉得应该使用哪一个并说出理由。
  • JSON——它是什么、为什么应该使用它、到底该怎么使用它,说出实现细节来。

重申一下,上述这些知识点都应该是你“想都不用想”就知道的东西。我一开始问的所有问题都是想摸清你对所有这些领域知识的掌握程度。虽然上面列出的这些知识点并没有面面俱到,但我觉得你至少应该掌握这些,才有可能跟我坐到一间办公室里来。

少量提问

我非常赞同面试者问的问题越少越好。反复问应聘者各种问题既不公平,也很无聊。我在任何一次面试中,通常只问三个大问题,但每个问题又会涉及我所能想到的多个方面。回答每个大问题一般要经过几个步骤,这样我就可以在每个步骤中穿插着问一些小问题。比如说: 查看全文 »

今天抽时间专门研究了一番仿真器(emulator)和模拟器(simulator),分析过程就不写了,下面直接给出结论;有不明白的地方,可以再看参考文献和网络词典及维基的释义。

仿真器,指的是几乎能够百分之百地模拟某硬件或软件系统的全部特性、行为的装置或程序。
模拟器,指的是仿照真实的硬件、软件、环境、条件,能够在某种程度上再现这些硬件、软件、环境、条件的装置或程序。

仿真是尽可能做到全方位的模拟,而且力求逼真,有点欲将原型或模仿对象取而代之的味道。仿真更具体,接近实物(也有说接近硬件的,但肯定不局限于硬件)。
模拟只是表面上做做样子,不会有真实的过程发生;但能够给出反馈,多用于研究和培训。模拟更抽象,侧重建模

当然,也会存在模拟器与原型的近似程度堪与仿真器媲美的情况,但它们的区别还是十分明显的,那就是模拟不够“真实”,而仿真非常接近“真实”。

在参考文献中“记性不好,所以写写”的原话基础上稍作修改,可以说:

如果原型是一个人,那么仿真就是克隆一个新人(这个人的言行举止与原型几乎一模一样),模拟就是把这个人生活中的某一段录成视频(能够据以建模)。

参考文献

1.海之雁 《仿真专业词义辨析之一——模拟与仿真
2.记性不好,所以写写《Simulation & Emulation
3. 丁刚 《详述软件开发中模拟器与仿真器的区别查看全文 »