2012年4月27日星期五

阮一峰的网络日志

阮一峰的网络日志


Javascript编程风格

Posted: 27 Apr 2012 03:30 AM PDT

Douglas Crockford是Javascript权威,Json格式就是他的发明。

去年11月他有一个演讲(Youtube),谈到了好的Javascript编程风格是什么。

我非常推荐这个演讲,它不仅有助于学习Javascript,而且能让你心情舒畅,因为Crockford讲得很幽默,时不时让听众会心一笑。

下面,我根据这个演讲和Crockford编写的代码规范,总结一下"Javascript编程风格"。

所谓"编程风格"(programming style),指的是编写代码的样式规则。不同的程序员,往往有不同的编程风格。

有人说,编译器的规范叫做"语法规则"(grammar),这是程序员必须遵守的;而编译器忽略的部分,就叫"编程风格"(programming style),这是程序员可以自由选择的。这种说法不完全正确,程序员固然可以自由选择编程风格,但是好的编程风格有助于写出质量更高、错误更少、更易于维护的程序。

所以,有一点应该明确,"编程风格"的选择不应该基于个人爱好、熟悉程度、打字工作量等因素,而要考虑如何尽量使代码清晰易读、减少出错。你选择的,不是你喜欢的风格,而是一种能够清晰表达你的意图的风格。这一点,对于Javascript这种语法自由度很高、设计不完全成熟的语言尤其重要。

一、大括号的位置

绝大多数的编程语言,都用大括号({})表示区块(block)。起首的大括号的位置,有许多不同的写法

最流行的有两种。一种是起首的大括号另起一行:

  block

  {

    ...

  }

另一种是起首的大括号跟在关键字的后面:

  block {

    ...

  }

一般来说,这两种写法都可以接受。但是,Javascript要使用后一种,因为Javascript会自动添加句末的分号,导致一些难以察觉的错误。

  return

  {

    key:value;

  };

上面的代码的原意,是要返回一个对象,但实际上返回的是undefined,因为Javascript自动在return语句后面添加了分号。为了避免这一类错误,需要写成下面这样:

  return {

    key : value;

  };

因此,

  规则1:表示区块起首的大括号,不要另起一行。

二、 圆括号

圆括号(parentheses)在Javascript中有两种作用,一种表示调用函数,另一种表示不同的值的组合(grouping)。我们可以用空格,区分这两种不同的括号。

  规则2:调用函数的时候,函数名与左括号之间没有空格。

  规则3:函数名与参数序列之间,没有空格。

  规则4:所有其他语法元素与左括号之间,都有一个空格。

按照上面的规则,下面的写法都是不规范的:

  foo (bar)

  return(a+b);

  if(a === 0) {...}

  function foo (b) {...}

  function(x) {...}

三、分号

分号表示语句的结束。大多数情况下,如果你省略了句尾的分号,Javascript会自动添加。

  var a = 1

等同于

  var a = 1;

因此,有人提倡省略句尾的分号。但麻烦的是,如果下一行的第一个字元(token)是下面这五个字符之一,Javascript将不对上一行句尾添加分号:"("、"["、"/"、"+"和"-"。

  x = y

  (function (){

    ...

  })();

上面的代码等同于

  x = y(function (){...})();

因此,

  规则5:不要省略句末的分号。

四、with语句

with可以减少代码的书写,但是会造成混淆。

  with (o) {

    foo = bar;

  }

上面的代码,可以有四种运行结果:

  o.foo = bar;

  o.foo = o.bar;

  foo = bar;

  foo = o.bar;

这四种结果都可能发生,取决于不同的变量是否有定义。因此,

  规则6:不要使用with语句。

五、相等和严格相等

Javascript有两个表示"相等"的运算符:"相等"(==)和"严格相等"(===)。

因为"相等"运算符会自动转换变量类型,造成很多意想不到的情况

  0 == // true

  == 0 // false

  0 == '0' // true

  false == 'false' // false

  false == '0' // true

  " \t\r\n " == 0 // true

因此,

  规则7:不要使用"相等"(==)运算符,只使用"严格相等"(===)运算符。

六、语句的合并

有些程序员追求简洁,喜欢合并不同目的的语句。比如,原来的语句是

  a = b;

  if (a) {...}

他喜欢写成下面这样:

  if (a = b) {...}

虽然语句少了一行,但是可读性大打折扣,而且会造成误读,让别人误以为这行代码的意思是:

  if (a === b){...}

另外一种情况是,有些程序员喜欢在同一行中赋值多个变量:

  var a = b = 0;

他以为,这行代码等同于

  var a = 0, b = 0;

实际上不是,它的真正效果是下面这样:

  b = 0;

  var a = b;

因此,

  规则8:不要将不同目的的语句,合并成一行。

七、变量声明

Javascript会自动将变量声明"提升"(hoist)到代码块(block)的头部。

  if (!o) {

    var o = {};

  }

等同于

  var o;

  if (!o) {

    o = {};

  }

为了避免可能出现的问题,不如把变量声明都放在代码块的头部。

  for (var i ...) {...}

最好写成:

  var i;

  for (i ...) {...,}

因此,

  规则9:所有变量声明都放在函数的头部。

  规则10:所有函数都在使用之前定义。

八、全局变量

Javascript最大的语法缺点,可能就是全局变量对于任何一个代码块,都是可读可写。这对代码的模块化和重复使用,非常不利。

  规则11:避免使用全局变量;如果不得不使用,用大写字母表示变量名,比如UPPER_CASE。

九、new命令

Javascript使用new命令,从建构函数生成一个新对象。

  var o = new myObject();

这种做法的问题是,一旦你忘了加上new,myObject()内部的this关键字就会指向全局对象,导致所有绑定在this上面的变量,都变成全部变量。

  规则12:不要使用new命令,改用Object.create()命令。

如果不得不使用new,为了防止出错,最好在视觉上把建构函数与其他函数区分开来。

  规则13:建构函数的函数名,采用首字母大写(InitialCap);其他函数名,一律首字母小写。

十、自增和自减运算符

自增(++)和自减(--)运算符,放在变量的前面或后面,返回的值不一样,很容易发生错误。

事实上,所有的++运算符都可以用"+= 1"代替。

  ++x

等同于

  x += 1;

代码变得更清晰了。有一个很可笑的例子,某个Javascript函数库的源代码中出现了下面的片段:

  ++x;

  ++x;

这个程序员忘了,还有更简单、更合理的写法:

  x += 2;

因此,

  规则14:不要使用自增(++)和自减(--)运算符,用+=和-=代替。

十一、区块

如果循环和判断的代码体只有一行,Javascript允许该区块(block)省略大括号。

下面的代码

  if (a) b(); c();

原意可能是

  if (a) { b(); c();}

但是,实际效果是

  if (a) { b();} c();

因此,

  规则15:总是使用大括号表示区块。

(完)

文档信息

2012年4月20日星期五

阮一峰的网络日志

阮一峰的网络日志


居延汉简和安阳殷墟1001号大墓

Posted: 19 Apr 2012 10:38 AM PDT

中央研究院是台湾的最高学术研究机构,里面有很多研究所。

此外,还有不少展览馆,可以免费参观。历史语言研究所的历史文物陈列馆,就令我大开眼界。

1.

"胡适纪念馆"的不远处,就是历史语言研究所大楼。底下两层是该所收藏文物的陈列馆

2.

陈列室的前厅,简洁而富有现代感。外人很难想象,这里收藏着代表着中国考古最高成就的文物。

3.

走进二楼的入口,迎面就是"居延汉简"的展室,令我惊喜异常。

4.

以前只在书上看过,1930年,中国和瑞典历史学家组成的"西北科学考察团",来到甘肃、内蒙交界处的荒漠,考察汉代边塞遗址"居延"。2000多年前,大汉王朝在那里每隔几里,就修建一个"烽燧",一旦发现匈奴入侵,里面的士兵立刻点起狼烟报警。后来,这些烽燧都成了荒丘。(上图为红城遗址,位于内蒙古额济纳旗,是居延地区保存最完好的汉代建筑遗址之一,照片取自互联网。)

5.

1930年4月底,考察队的瑞典历史学家弗克•贝格曼(Folke Bergman)进入了一座汉代城堡,他发现"城堡东侧是宿舍和厨房,还有一间不足6平方米的小屋,里面有成册的木简,其中一份是汉元帝永光二年(公元前42年)一个下级武官丧父的报告书,另一份为汉和帝永元五年(公元93年)的账簿。专家们推测这里可能是当时的档案室,后来的发掘证实了这一推断。"(图为汉代要塞的复原图。)

6.

考古学家们大喜过望,将考察重点转向发掘这些汉代书简,结果一共挖到了1万多枚,统称为"居延汉简"。它们大大加深了我们对汉朝的了解,国学大师王国维兴奋地将其与安阳甲骨文、敦煌藏经洞、紫禁城大内档案,一起并称为"20世纪中国文化界四大发现之一"。(图为出土时的居延汉简。)

7.

1949年,这批宝贵文物被运到了台湾,从此我们只能在书上读到。今天,我能亲眼目睹,怎不激动。眼前的中央展柜,存放的就是这批汉简中最长的一份----77根汉简组成一张武器清单,上面记载着要塞中釜、弩、箭等兵器的清点结果。

8.

看一下细节。

9.

这个就是当年弗克•贝格曼发现的第一份木简。公元前42年,一个姓郑的军官,因为父亲去世,要求请假回内地奔丧。这份木简完全保持原样,连上面的绳子都是汉朝留下来的。

10.

"居延汉简"的内容,大部分与军事有关,比如记载匈奴的动向。

11.

也有不少反映政治的内容,比如皇帝的诏书和各种敕令。以及反映日常生活的内容,上图就是随军家属的领粮记录。

12.

除了汉简之外,还挖掘出了一大批其他文物,使得我们仿佛看到了活生生的汉代戍边士兵的生活。上图为画着人脸的木片,大概是士兵用来避邪的。

13.

这个楔形的木器,初看不知道是什么东西。

14.

红外线下,才发现上面写有文字。原来,它是用来封囊袋的,袋子的口就穿过木器上方的孔,上面的文字则是记录了袋子里面的东西,大多数是衣服。

15.

士兵用的木杯子。

16.

汉代的梳子。

17.

汉代的毛笔,木简就是用这种笔写的。

18.

用来射匈奴的箭杆。

19.

士兵吃的谷子。这是考古学家一粒粒捡起来的,放在随身的火柴盒里。

20.

所有这些文物,都是2000年前的东西。当我与它们面对面的时候,觉得汉朝也不是那么遥远,甚至触手可及。范仲淹笔下的西域大漠,"长烟落日孤城闭,羌管悠悠霜满地",仿佛在眼前浮现,而戍边士兵的心境"浊酒一杯家万里,燕然未勒归无计",仿佛与今人是如此相通。(上图为考古学家整理和辨识汉简的笔记。)

21.

二楼的其他文物,这里就从略了。不过,值得一提的是,我第一次看到"金榜题名"的"金榜"。

22.

这张是科举考试的"试题",题目非常长,深奥难懂,怪不得要考三天。

23.

来到一楼,我发现这里正在举办"稀世之珍----西北冈一OO一号大墓特展"。这下我真的惊呆了,我原先觉得二楼的文物已经很珍贵了,但是与一楼相比,几乎不值一提。这里每一件都是无价的国宝,故宫博物院也看不到,是史语所最珍贵的收藏。更难得的是,那天下午,整个展厅只有我一个人,可以慢慢地、近距离地观赏。

24.

20世纪初,中国学术界根据流传出来的甲骨,认定河南省安阳小屯村是3000多年前商朝最后一个都城。1934年,历史语言研究所发现,小屯村西北角的山冈是商朝的王室墓葬区。

25.

这是小屯村的卫星地图。

26.

在西北冈一共发现了八座商代帝王墓(google地图)。

27.

第一个挖掘的大墓,就被编号为1001号。后面发现,这是这八座商王墓中最大的一个。

28.

1001号大墓呈十字形,东西南北四个方向皆有墓道,墓室位于中央。气势宏伟,堪与古埃及的帝王陵媲美。

29.

这座大墓中发现了164个殉葬的头颅,是现存商王墓中最多的,有的历史学家推测,这座墓的主人是商王武丁,否则不可能有那么多人陪葬。

30.

1001号大墓出土了许多令人瞠目结舌的珍贵文物,现全部收藏于台湾的历史语言研究所。其中最令人称奇的,就是许多造型奇特的动物。上图是青铜器盖子上的一条龙。

31.

玉雕的大象。

32.

乌龟和青蛙。

33.

大理石伏兽。

34.

大理石立雕。

35.

大理石老虎。

36.

大理石鸟首。

37.

大理石人身虎首。

38.

人身虎首的侧面。

39.

大理石猫头鹰。

40.

大理石小鸟。

41.

大理石牛。

42.

还有一些非常夸张的人面造型。

43.

看着这些奇特的文物,我心中浮现出了一个大大的问号。

目前,可以被验证的最早的中国朝代,就是商朝。再前面的三皇五帝和夏朝,纯属传说,根本找不到文物来证实。从这个意义上说,商朝(具体一点,安阳殷墟)就是中华文明的最早现身。

44.

但是,看了上面这些雕刻,你觉得这像中华文明吗?

为什么商朝以后,这样奇特的、富有想象力和生命力的造型,再也没有出现过,中国人的艺术追求反而日趋刻板、精致、拘谨、苍白?

45.

春秋战国距离安阳殷墟的年代,大概只相差七八百年,但是艺术品的造型已经完全不同于商朝了,夸张的想象力再也看不到了,表现伦理、礼教、生活起居的内容越来越多。此后,中国人的想象力进一步衰退,如果不是佛教在汉代传入中国,古代中国人也许都不知道什么叫神话了。

为什么我们说敦煌壁画如此美丽动人?因为画的都是充满想象的佛教题材,中原文明根本没有这种内容。佛教传入之前,中国人对生、死、神、鬼的想象,简陋粗糙到完全可以忽略。

所以我们要问,为什么商朝人的艺术想象力没有传下来?

(完)

文档信息