What is 'this'? - Part.1March 24, 2010

呃,这次的标题有些“装逼”,首先我们从道题目开始。

这是道有趣的题目:考虑下面的代码,考虑 console.log 输出的值:

var x = 10;
var foo = {
    x: 20,
    bar: function () {
        var x = 30;
        return this.x;
    }
};

console.log(
    foo.bar(),             // 1.
    (foo.bar)(),           // 2.
    (foo.bar = foo.bar)(), // 3.
    (foo.bar, foo.bar)()   // 4.
);

-- Split --

实际上,题目真正意思求 console.log 中依次四条语句的值。为了方便讲述,上面的语句分别标注为 1-4。

首先,是“1.”这条语句相对来说比较明朗(其实我们也经常这样写)。调用 foo 的 bar 方法,因此 bar 的 this 指向(作用域)为 foo,因此就等于是取 foo 上面的 x 属性(也就是 foo.x)的值,那么语句返回的值就是 20 。

然后是“2.”这条语句。我们可能对 Grouping Operator (也就是“()”)犹豫不决,那 么我们找找 ECMA 中相关定义

11.1.6 The Grouping Operator

The production PrimaryExpression : ( Expression ) is evaluated as follows:

    1. Evaluate Expression. This may be of type Reference.
    2. Return Result(1).

NOTE 

This algorithm does not apply GetValue to Result(1). The principal 
motivation for this is so that operators such as delete and typeof 
may be applied to parenthesised expressions.

因此,由于 foo.bar 是个引用“Reference”,所以使用组操作符 (foo.bar) 返回 的引用是和 foo.bar 是一样的。

如果还不理解,那么考虑下面的表达式:

console.log(foo.bar === (foo.bar))

因此,

(foo.bar)();

返回的也是 foo.x 的值,也就是 20 。

目前为止上面的前两个语句的解释,想必已经了解。细心的读者会发现,其实题目的重点是在 3. 和 4. 两条语句。

要解释后面的两个语句恐怕这篇文章会塞不下,请留给我点喝水的时间,我们下篇继续。

-- To be continued --

PS, Part 2. 在这里

生活、读书、新知March 22, 2010

记得中学的时候从书店的角落中不经意翻到本“野史”,自此就对教科书外介绍的另一面历史感到情有独钟。书的名字自然已经不得不遗忘,但书的出版社却已经记得清清楚楚。

由此,喜欢上“野史”的同时,也爱屋及乌得喜欢上这家名叫三联书店的图书。同时,它的“生活、读书、新知”这三个词语,也深深得烙进了我的灵魂中。

读书能获得新知,从而充实自己的生活,但现世的浮躁,已经很难让人静下心来慢慢得咀嚼完一本好书。想起在某本书中碰到的段话:

“我们生活在信息爆炸的社会,我们所遇到的问题不
是信息汲取的困难,而大脑无法辨认真正我们想要的
信息。

我们习惯每天上网拿着鼠标面对冰冷的显示器查找我
们所需要的信息,却忽略了我们身边随时可以‘请教’
的老师。”

每天面对 Google Reader 的信息爆炸,甚至是 1000+ 的未读信息,是不是有强迫自己继续读下去生怕自己会遗漏某些重要的信息?

相信我,如果真的有那么多信息,你也不可能全部消化,更不用说找到有用处的信息。那么,你还不如直接 Shift + A 让这些“多余”的信息直接在面前消失,然后去做更加有意义的事情。

是的,我承认曾经我也碰到了这样两难的境地,甚至我怀疑我有强迫症的倾向。

http://pic.yupoo.com/feelinglucky/5260790a5175/medium.jpg

via

A:在我的新闻阅读器中,大概有 300 个种子。
B:什么是新闻阅读器?
A:你不知道 RSS、ATOM 这些玩意?
A:你到现在还不会直接访问他们的站点每个挨个去阅读吧?
B:当然不会,我会把它们打印出来然后吃饭的时候慢慢阅读。
A:好吧,这是你的信仰。

其实上面的可能不仅仅是个笑话。所以,如果你明白能下面的些道理,那么我相信你了解自己需要些什么

  1. 看过的信息不代表就是你的,好记性不如烂笔头
  2. 时间和精力都是有限的,但它们都是资源
  3. 永远不要强迫自己做什么,如果真的需要如此,那么至少努力让自己不会厌恶它
  4. 如果觉得自己没时间,那么尝试在厕所扔本书,即便是杂志也好
  5. 睡觉前半小时不要碰任何电子设备

还是那句话,大道理其实谁都明白,做与不做是另外回事情。

说到书店,顺便说下杭州的书店。其实让人担忧的是,杭州的书店在逐渐得减少

现在的人们,不是在咖啡吧谈论生意、就是在酒吧讨论风月,因此让人对这些场所已颇感“敬畏从而远之”。而那些“纯粹”的书店 -- 这对于宅男们仅存的宿营地,也正在不断被商业社会淹没。

-- EOF --

Re:新手虚心求教March 10, 2010

经常有朋友邮件过来咨询技术问题,本人不才经常不是忘记回复就是回复的比较迟。原因是一来本人比较懒(或者可以托词为忙),二来是怕“误人子弟”。

当回复这位仁兄的邮件时,不觉得就发现回复的字数越来越长,于是就将其整理为篇 Blog。我的意图是不仅仅帮忙解决问题,而且能提供个解决类似问题的思路。

邮件原文

来自: Captain
时间: 2010-02-28 20:41
话题: 新手虚心求教

  你好,我是刚刚入门学习Javascript的新手。我想向你请教一下我在学习过程中所
遇到的一个问题。恕我愚昧,但是我一直无法理解,恳请赐教。 
  我在学习中碰到过一条这样的声明: var !myVariable != variableValue, 因为在
以前的学习中知道双重否定等于可定,那这则声明是否可以理解成 var myVariable = 
variableValue ?
       若非如此解释,恳求正解。冒昧打扰请多多包涵。

我的回复

不好意思,收到你的来信到现在才回复。第一眼看见您提供的代码,个人觉得它不合乎语法规则

var !myVariable != variableValue

根据 ECMA 相关的文档,var 关键字的定义在 12.2 章节(我看的是第五版),它的语法定义是:

var VariableDeclarationList ;

而 VariableDeclarationList 包括

VariableDeclarationList , VariableDeclaration

上述两个定义又包含多种情况,说起来有些复杂,所以我画了张草图(可能不准确,以文档为准):

http://files.gracecode.com/2010_03_10/1268192678.png

所以,上面的表达式不符合 var 语句的定义要求,因此 Javascript 解析器会报语法错误。

如果是非赋值定义语句,也就是

!myVariable != variableValue

那么就是个条件判断语句,其中有两个条件判断操作符“非(!)”以及“不等于(!=)”,那么我们就要了解它们的结合优先级。

根据相关的参考文档,我们可以得知“非”操作符的优先级比“不等于”要高,因此语句先计算 !myVariable 这块,然后再计算“不等于”后的值。

至于能否改成其他等同的逻辑情况,这里还有个问题就是值取“非”的时候会有多种情况,这里有个讨论:

明城: 
问: !a != b 是否等于 b == !!a

崇厚: 
这个还要看数据类型吧?
比较运算符的优先级是最低的

渔隐: 
照这样推理就是a == b 了

崇厚: 
a = ''
b = 0
console.log(!a != b)
console.log(b == !!a)
true true

明城: 
关键还有个“非”操作符,所以 B 始终是和布尔值对比的

崇厚: 
我试出来三个结果
t t 
t f
f f

痴灵: 
var a = 0;
console.log(!a);console.log(typeof(!a),typeof(a));
true boolean number
类型发生了变化了

渔隐: 
用!== 和===吧

明城: 
不纠结了,以后记得逻辑表达式里千万不要加一元操作符
或者加括号

沉鱼: 
有个比较有效的做法,不太记得操作符的优先级时,我都
加(),这样虽然比较挫,不过保险

崇厚: 
不管记得不记得优先级,表达式比较复杂时最好都加括号
这样看起来清晰一些

举一反三,以后如果再碰到类似的问题,我们可以:

  1. 查文档。ECMAScript 规范MDC 中的文档、甚至 Google 都是我们的好帮手
  2. 如果还是无法理解,可以“偷懒”先看运行结果,然后逆向推断
  3. 团队的力量胜过一个人闭门造车

-- EOF --

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. ...
  10. 129
Yahoo 统计