从“装B被雷劈”讲起

  

从“装B被雷劈”讲起

 

(谨以本文,积极响应《JavaScript征途》读后感写作有奖召集令!参见这里……) 

(最新进展,《真相总是能被还原的——兼批一切口号党、标题党与托托党!》参见这里……

 

 

从“装B被雷劈”讲起
=======

关于我对《JavaScript征途》这本书在51js.com上的讨论在这里),readkid 在 blueidea.com 上说了一句:爱民真有范儿。这话,说得我真脸红。这次是真正脸红,不是装——我又不是明星要人,既然不是,还有人家的那个“范儿”,是我的错。做人做到不诚恳,这就是毛病。用时下流行的话来说,就是“莫装B,装B被雷劈!”

话粗,理是对的。有人喜欢这么讲,也有人喜欢那么讲,比如“君子坦荡荡,小人长戚戚”,于人于事,我还畏言畏行,不是“长戚戚”么。

好。我们回头来说理。王昊同学曾经说“有些时候的争论,不是为了正误,而是为了面子”。这话很好,我给画到“架构师能力模型图”里,还给写到了文章里头,时时拿来自省。然而这两天,又忽有领悟,觉得王昊这话原来还是只说了一半。另一半,也是可以反过来说的,就是:

有些时候的不争论,也不是为了正误,而是为了面子。

比如我在51js.com上的不争论,把自己置身事外,以及看起来的那个所谓的“范儿”,其实,并非因为朱同学或hax同学的正误,而不过是为了面子。

撕掉面子问题,我们来谈谈事呢?是所谓“君子和而不同,小人同而不和”。其实我并不认可朱同学的言论与行为的,表面上我们却做成了一团和气,朱同学还一声声“爱民”地称呼着,仿佛我与他熟识一般——话到这里,我们论坛上讨论,就用论坛ID好了,大名叫上来,听起来就不真诚,也无宜于谈是论非。所以呢,这个局面,也就是所谓“(表面上看来)同,而不和”,做成了小人一般。

所以无怪于readkid说我“有范儿”的时候,我的脸红得跟猴屁股一般。自己也有小人之行,别人揭了出来,哪能装得没事人一样地呢?就算哪天有我这个心思,也怕没那个脸皮,厚得可以遮住屁股红。

 

好不好呢?是个问题。
=======

所以还说回来。朱同学的书好不好呢?是个问题。我的答案是:不好。而且是:相当不好。

因为要听我的意见嘛,自然要从我的角度上来讲,而不是从他所谓的“初学者的”角度上来讲。初学者喜欢什么,我们就给什么,那不也是误人子弟么?初学者的选择能力弱,分辨能力弱,这是众所周知的,但如果因为这个,我们就塞给人家毒品,还说“人家喜欢”——那不是犯罪么?而且还是利用人家弱点的犯罪,前者是为不义,后者是为不德。所以前两年确有出版社约我写“给初学者的书”,我拒了,我没那个道行,写不出来我就不接嘛。

那我——主观地啊——认为应该给初学者看的书是如何的呢?首先的、起码的,要“没错”!这是第一要务。你可以不写,可以留问号,可以说“参见”,但是,要写出来,就起码要“不错”。例如:

JavaScript 里面有6种基本类型,对象是其中一种,各种对象是“对象(object)”这一种类型中的子类(类型)。

这是基本常识。如果要讲错了,把HTML中的DOM对象说成是基本,或把null说成是类型,那就是的确错了,教坏了新同学。但是朱同学就是要犯这样的错误。他写道:

JavaScript 语言只有 3 种最原始的数据类型:数值型、字符串型和布尔型……JavaScript 还定义了几个特殊的数据类型,如空类型(null)和未定义类型(undefined)。基本数据类型按值传送,而复杂数据类型按引用传送。

这样的写法不但是“错”,而且还相当可笑。这样的写法,难道就是“让初学者看得更懂”吗?或者不这样写就无益于初学者阅读了吗?绝对不是!显然不是!而更显然的,不过是作者在基本概念上的模糊、糊涂!以及,根本上连一些手册都没读明白,写东西不过是“想当然尔”!

作者朱同学的问题在于:他不单不认为这是个问题,还认为作为读者的——初学者,理所应当地应该接受他的这种写法。

这种写法到底是什么样子的呢?

1、扯虎皮拉大旗

对初学者,用汇编、机器指令甚至于敏感电流的强弱来充塞门面:反正你也看不懂,我说说说就说说,起码看起来比你高端。

2、语言轻佻视为乐趣

书中说,“柔弱的JavaScript 语言——JavaScript 是一种弱类型语言,其柔弱性具体表现如下……”我真的不明白,讲语言的性质有讲“柔弱性”的吗?又不是评价人家小姑娘的小蛮腰。

3、把随意猜想当成理论系统

例如把数据分成值类型和引用类型——这是可行的,但——然后说“值存储在栈中、引用类型存储在堆”中。这是典型的:
  – 把动态语言当成静态语言讲
  – 把解释语言当成编译语言讲
  – 把猜想当成理论讲

能犯的错在这里都犯了,能乱讲的都尽可能地讲乱了。又尤其是朱同学后面给出了一个“栈和堆数据结构比较”,要是初学者拿着这个表格进考场的话,哈哈,监考老师都不用抓,反正抄出来也是个不及格!

所以,我的答案是:相当相当地,不好!

 

不好,不好你还不说,害人掉坑里头!
=====

有一张图,一个人站在大坑前面自说自话,全然不顾后面有人掉进了水坑:

 

是谓“小人”!当人做成了君子模样,行为上却还是小人的话,那就是危害大了。比如我前面的那个“范儿”,就让我做了回小人:你知道不好,你为啥不说?!

月影同学写的书《JavaScript王者归来》我看过样章,就提了大把意见给他。我特地在MSN里跟月同学一一讨论。但书出版了,我就什么话也不说了。这是一种不说,叫“先说后不说”。朱同学的书还没出,发了样章,我觉得不好,但没啥交情在里面,所以也不会象给月影那样地发个消息去讲讲;直等到hax同学揭批了,列了个清单,我才去分析下错误,然后就停下不说;最后两方面的把事情吵得天响,等到有人来揭我的“范儿”了,我又才跳出来说话。这也是一种不说,叫“先不说后说”

总是有“不说”的行为在里头的。为啥“不说”呢?为啥不跳出来一一说清楚呢?

一是你得看给谁说。《观止》这本书就相当好,责编前些天跟我讨论,我就直言:书做得没品味、粗糙;这么好的书,做成这样,不如重做!果真,人家责编就冒着影响业绩的风险,停止了旧版的印刷发货,赶着工夫做新版,采纳了我的几条建议:把目录做细、把纸张用好、把背景说清。这位责编,我就佩服。佩服啥呢:能广开言路啊!出版做啥?买纸挣钱啊!你说他纸都用不好,不跟挖他财路差不多吗?哈,人家听得进去。好编辑!这就比拿多少个大奖要好!因为人家是真为作者做书,为读者做书。

二是你也得看怎么说。出版社的朋友问我对朱同学这样事的看法。我在MSN里头说:“我觉得,作为对作者的珍惜,在出版之前,能在作者之间相互沟通,多多互助,这是很好的。非得等到出版了,大家一拥而上地去批评,人家接受不了,也是正常。”所以呢,如果真想评论什么,就不要掐着人家咽喉说“你听我说呀!”屁话,人家都快被你掐死了,还听你说个鬼啊?

所以,道理我是懂的,我也在做。但是呢,这件事的双方都要明理才行。你给人家讲讲好坏,人家不听,反倒嫌你挡了人家晋升的道途,反倒说你说的是恶言,要把你放在老虎凳上过过堂。那,接下来的争论,不是为了正误,而是为了面子——就成必然的事情了。

反过来说,为了面子而不说,也成了必然的事情了。

 

我为啥不说?
=====

出版社的朋友问我为啥不说话?我说,如果我没写JavaScript的书,我大概会发言的。因为我写了一本,朱同学出同类的书,我就要跳出来“喊打喊杀”,好象说不通。

有小人心啊!——现在我就是这么看自己的。我出言批评别人了,并不见得就是在把自己“立为正统”,别人真要这么想,我没这心思不就成了?!再者,朱同学再来辩解的是所谓“学术问题”吗?不是啊!那些都是“基础问题”,基础问题讲不清,误人啊!看着误人,跟看着人跳坑里有区别吗?

小人心啊。

所以我不说,是小人心在作祟。说出来,别人再说我小人,起码也是真小人哈。儒家啊,你分个啥小人君子嘛。还是佛家说得好嘛:本心做事,心即是佛。所以我们不妨高喊着“起来!起来!”把那些做着样子的,装着“范儿”的,都拍到他们自己挖的坑坑里头去:

 

所以呢,我想要说的是:大家都拉下架子,我也没那个“范儿”了,朱同学也没有那个“范儿”了。由此开放言路,我们都来讨论技术,才有得发展。批评是要的,自我批评也是要的,接受批评更是要的。做错、写错、表错情都没啥了不得的,能自降一格,真正虚了心的去听人骂、接受、改进,“范儿”才会由外至内的消失,这才是真情、真知。没有真心对人,没有虚心对事,你发个贴来甚?拉那么多人来做招牌做甚?心不在了,于诸事无益,骂仗还会继续,看客也还将口水。

最后,关于用心,我还是再讲讲那个故事吧:

我藏行的路上,就看见过朝圣的信徒们,三步一叩首地行进着、行进着……到得寺庙之前,用酥油给佛像贴上一块钱一角钱一分钱,分分角角摞满寺庙的山墙。然而信徒们,贫苦的依然贫苦着,羼弱的依然羼弱着,迷惑地绕行于山墙之外的转经路上。这情景,恰如同那些书本上的标题,以及被标题蛊惑着、燥热着的读者与“作”者。

我便真到过一个在翻新的寺庙里去,见到过一尊没有金漆彩描的佛像。绕到他的背后看去,在左上、肩下的位置有一个方形的孔洞。那时我问庙里的住持,这个孔洞有什么意义呢?住持说,在佛像落成之前,要请了经文放进去,那是佛像的心的位置。En…连做法事的老住持也知道,只铸个泥菩萨在那里是没用的,华衣锦服的名头下面,有没有解决问题的实质,方可见真正的良心。

 

(又,关于这本书的“技术讨论”,我另发博客。这里我只自顾自的反省与揭批先。)

  1. #1 by on 2009年09月24日 - 1:11 上午

    你可以不写,可以留问号,可以说“参见”,但是,要写出来,就起码要“不错”。 —— 这才是严谨治学的态度。然后说“值存储在栈中、引用类型存储在堆”中。 —— 很多人就喜欢这样,不是为了育人、分享, 仅仅是为了装逼,而且还装出纰漏。

  2. #2 by Unknown on 2009年09月24日 - 2:31 上午

    Null是类型这没错http://bclary.com/2004/11/07/#a-8刚跟Aiming聊了两句这里有个关于Winter和winter的小故事http://bbs.51js.com/redirect.php?goto=findpost&pid=596899&ptid=85553

  3. #3 by kai on 2009年09月24日 - 4:18 下午

    错了认个错就是了。错了死撑,难怪这么多人火。

  4. #4 by Shaozong on 2009年09月25日 - 9:31 上午

    批斗者与被批斗者;互联网上铺天盖地的宣传,活灵活现的追捧,各大“牛人”鼎力出场。一朝被揭,立马骂声一片,反思的,追悔的,看热闹的,打酱油的。。。这样的环境,这样的人群,即使这本书真的值得一看,也懒得一看。 看书必先观其人,人品是会映射到书中的。

  5. #5 by shawn on 2009年09月25日 - 10:21 上午

    看阁下评论如此强大,我倒是想找本《js征途》收藏,无聊的时候解解闷

  6. #6 by xin on 2009年09月25日 - 11:31 上午

    以前,太祖说过:世界上怕就怕认真二字后来我体会到,世界上怕就怕不认真三字。 这一次认真的人和不认真的人碰上了,究竟谁怕谁呢?

  7. #7 by 裕波 on 2009年09月25日 - 4:07 下午

    写得我都看不懂,太古文了!

  8. #8 by on 2009年09月25日 - 11:22 下午

    这篇挺好,一气呵成。好些观点还真是一针见血。

  9. #9 by argb1985 on 2011年07月25日 - 2:59 下午

    JavaScript 里面有6种基本类型,对象是其中一种,各种对象是“对象(object)”这一种类型中的子类(类型)。

    这话什么意思?
    六种基本类型?哪六种?请问什么是基本类型(primitive type)?
    对象如何成为primitive type?

    你对概念的混淆更严重,js有五种基本类型number,boolean,undefined,string,null;不过null是有点特别typeof null的结果是object
    剩下的数据类型只有一个object,但是上述几种基本类型除了null也可以包装成object比如new Number(1)

    • #10 by aimingoo on 2011年07月25日 - 3:15 下午

      我想很难很快速地解释你的问题。那么,接着你的思路,我就问几个问题好了:
      1、函数是不是类型?是什么类型?
      2、为什么说JavaScript中的函数是“第一型”的?
      3、undefined如何“包装成object”?即使你所说的是笔误,那么对于“一切都是对象”的JavaScript,undefined是什么?
      4、true与Boolean(true)在类型上有什么不同?

      最后强调一下你的用词问题:Undefined是类型,undefined是值,’undefined’是类型的名称。此外,应留意JavaScript中存在着值类型与引用类型。

      • #11 by argb1985 on 2011年07月25日 - 4:17 下午

        对于您这么快的认真回复表示感谢,那我们就这个问题讨论下吧,如果我确实理解错误也正好纠正下,对我也是个很好的机会。
        我认为继续之前我们先理清几个术语
        type:这个词也就是我们所说的类型
        class:这个词也就是我们所说的类
        好了,我认为js里面可分为这么几个type:number,boolean,undefined,null,string,object,除了object剩下的便是primitive type,而object可以认为是一种复合类型

        1、函数是不是类型?是什么类型?
        函数不是类型,函数是函数,是类型(type)为object的一个分类(class),一种特殊的object,可以执行(实现了内部属性[[call]])
        2、为什么说JavaScript中的函数是“第一型”的?
        这句话也时常听说,但是不知道出自何处,这个“第一型”不知道指的是type还是class,不过这里从强调函数在js中的重要性的角度来说是没问题的,不过据我了解js被发明时借鉴了Scheme(函数式语言),所以有了first class这个特点,关于js的诞生请参见http://www.ruanyifeng.com/blog/2011/06/birth_of_javascript.html,我想您说的“第一型”,可能存在理解上的偏差,也许是翻译的有问题导致的,总之是first class没错,函数之于js确实重要
        ps:type更强调种类,class更强调级别,有高低之分

        3、undefined如何“包装成object”?即使你所说的是笔误,那么对于“一切都是对象”的JavaScript,undefined是什么?

        这个问题我确实不知道怎么回答好,不过既然提出来了我就说下我的理解
        先从简单的来吧,”undefined是什么?” undefined在概念上是类型为undefined值为undefined的这么一个东西;权威指南上如是说:undefined is a predefined global variable (not a language keyword like null) that is initialized to the undefined value.(参见,第六版 3.4 null and undefined)

        “一切都是对象”的JavaScript”,这句话我认为不能说一定正确,比如一个字面量并非是什么对象,1就是一个数值,只有1通过某种方式成为一个object的时候才是对象,比如new Number(1);
        undefined如何“包装成object”? 不能,他本来就不是个object,也无法包装成object;

        4、true与Boolean(true)在类型上有什么不同?
        true 是boolean类型的一个值,Boolean是一个build-in Object,并且是个函数(特殊的可调用object);

        当这些字面量在进行某些表达式运算时可能会转换成其对应的某类object,这个没有深究过。

        您最后的强调我是认可的,存在着值类型和引用类型,并且值类型在某些情况下可以转换到引用类型,比如var one=new Number(1);

        这些观点都是我在参考相关资料后的加上自己的实践和知识后的个人理解,也许有错误,如果能得到纠正将不胜感激。还有就是许多概念的混淆与我们所处的语言及文化环境是有关的,如果我们处在英语的语言环境下也许会少些。如果有人能对js引擎的源码进行一个详细分析再配合相关文档去理解应该问题会更少。

        请多指教。

    • #12 by aimingoo on 2011年07月26日 - 3:44 下午

      谢谢。写了一篇超级长的,所以发到下面了。
      http://blog.csdn.net/aimingoo/article/details/6634977

  10. #13 by argb1985 on 2011年07月27日 - 1:43 上午

    csdn真是不方便回复,还是回到这里吧。

    为了保持和谐的讨论氛围我先表表立场,首先我不是为朱先生打抱不平的,我也不认识他;其次我对爱民老师一直也都是很尊敬的。

    我是无意间看到这篇文章的,然后就发表了下自己的看法。

    经过前面的讨论,有些地方我确实表述的有些偏差,比如我所有的地方都用小写,您也指出了:“最后强调一下你的用词问题:Undefined是类型,undefined是值,’undefined’是类型的名称。”,今后我会注意这一点,描述类型(type)首字母大写。

    在您刚才的回复中提出了两套类型系统,对于这个两套类型系统不知道您的依据是什么?不管是出于对其类型系统理解起来方便的考虑还是别的什么角度,在此我也不想做对与错的讨论了。不过我还是坚持一下几个观点:

    1、javascript 语言类型(language type)只有六种:Number,Boolean,String,Undefined,Null,Object,您打开ecma规范,看其目录,点开8 Types,可以看到从8.1到8.6列出了这些类型,但是types里面没有function,也没有Function,更没有Function()。

    2、函数是一种特殊的object,Object类型的一个分类(class),尽管typeof 对一个函数的运算结果是function,但仍不能作为一种type。对于您提到instanceof的问题,我认为type是type,instance是instance完全不是一个概念,倒是作为识别某个对象属于某种对象分类的手段似乎更合理。

    3、“一切都是对象”这句话我也一度将其奉为经典过,但现在至少我认为是不严谨的,甚至是错误的,容易误导人。我很想知道其出处。

    4、first class 只能说强调了函数的重要性,将其译作作“第一型”本身就有问题,容易误导,我也曾经被误导过,如果撇开计算机,撇开程序再去理解first class 也许能更好的理解其语言含义:”头等的“,跟类型完全没关系,我只想说 first class not first type.

    5、对与我前面提到的primitive type(基本类型)的叫法,也并非我自己臆造的词,主要依据如下:

    a)、
    ECMA-262 5.1 Edition / June 2011 ——-9.1 ToPrimitive
    The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType to favour that type. Conversion occurs according to Table 10:(表省略,可自行查看).

    期中提到primitive type

    b)、你已经列出的那段关于property的引用,不在重复,相见 ECMA-262 5.1 Edition / June 2011 ——-4.2 Language Overview

    c)、Javascript The Definitive Guide 6th Edition——–Chapter 3. Types,Values,and Variables,第二段:

    JavaScript types can be divided into two categories: primitive types and object types.
    JavaScript’s primitive types include numbers, strings of text (known as strings), and
    Boolean truth values (known as booleans). A significant portion of this chapter is dedicated
    to a detailed explanation of the numeric (§3.1) and string (§3.2) types in Java-
    Script. Booleans are covered in §3.3.
    The special JavaScript values null and undefined are primitive values, but they are not
    numbers, strings, or booleans. Each value is typically considered to be the sole member
    of its own special type. §3.4 has more about null and undefined.

    当然这里并没说null and undefined是属于primitive types,而是说成 special type,从这个地方来看,您前面提到的朱先生的书中的内容”
    JavaScript 语言只有 3 种最原始的数据类型:数值型、字符串型和布尔型……JavaScript 还定义了几个特殊的数据类型,如空类型(null)和未定义类型(undefined)。基本数据类型按值传送,而复杂数据类型按引用传送。“
    也并非完全无根无据的瞎说,至少不至于像您说的|

    “这样的写法不但是“错”,而且还相当可笑。” 那么严重。

    最后说明下我把primitive type叫做基本类型,也有叫做原始类型的,我现在也说不好哪个叫法更复合逻辑些。
    我前面也提过,我的这些观点是基于 某些参考+实践 得出的,也许会存在错误,但至少目前我认为这些观点是合理的,对某些像”一切皆对象“、”第一型“之类的看似正确的说法的评价也是不为过。

    另外,这里顺便提一下,我对所谓的”预编译“一词也不甚理解?不知道是谁第一个提出这样的说法?编译就编译,何来预编译?莫非指的预处理,不过也不像,也许用这个词可以解释某些语言现象,不过在概念上确实让人迷糊。这里请爱民老师给指点下^_^

    理是越辩越明的,一直以来没有被质疑过的东西未必就是对的,已经被广泛接受的东西也未必是对的,我尊重权威人士,任何问题我也期望得到权威的解释,但我也会毫无顾忌的质疑权威,今天我们一老一少的讨论让我也加深了对相关概念的认识,在此表示感谢。

    • #14 by aimingoo on 2011年07月27日 - 2:11 下午

      仍是回复了在我的博客上:
      http://blog.csdn.net/aimingoo/article/details/6636961

      其实,重要的是ECMAScript并不是强调语言类型的分类,也不强调JavaScript/ECMAScript是多范型语言这一事实。所以以它的定义来讨论一些问题,会有点讲不清。

      关于预编译,一般是指预处理。不过很多编译器是采用“多道编译”的方案,也就是并非一次就生成了二进制代码。往往的,会有中间代码,或者处理交叉链接(库)的情况,所以往往三次、更多次的编译都有。这些情况下,确实不好说哪一次或哪几次才是“预编译”。这一点应该视编译器而定。

      最后,我不是权威,尽可质疑得;另外也不算老呵。

  11. #15 by argb1985 on 2011年07月27日 - 3:35 下午

    对于这个议题就到此为止吧,虽然有些地方不能达成一致,如果有一天我发现自己某些地方错了,我会认错、纠正的,我想您也应该一样。不过目前为止我还是保留自己的观点。

    再次感谢爱民老师不厌其烦的认真回复,另外请把我名字改为argb吧 哈哈

  1. 再谈JavaScript的数据类型问题 | 前端分享
  2. 再谈JavaScript的数据类型问题 | iCoding

留下评论