無標題文檔

推荐《jQuery 1.4 动画技术》

https://files.gracecode.com/2011_05_30/1306744111.jpeg

编写网页脚本某种程度上说,不仅仅是光光技术方面,同时需要考虑到很多非技术因素,例如使用动画带给用户体验方面的影响。

而从实际情况下看来,很多为了所谓效果而使用的动画,其实这往往会适得其反。同时,还有很多新手对于动画还保留着莫名的恐惧感。

这里推荐的这本书的名字叫 《jQuery 1.4 Animation Techniques: Beginners Guide》 。但并不要被它的书名所迷惑,总体阅读下来这本书还是需要有一定的基础。Amazon 上有读者就抱怨,‘"beginning" is a little bit of a misnomer’,不过这不影响这本书的所提供的营养价值。

不过还是要抱怨下,本书的后两个章节在我个人看来有些鸡肋。使用 CSS3 以及 Canvas 等「新技术」完成动画并不是什么新鲜的技术,所以加入这些内容未免有些凑数的嫌疑。

三百多页的书,所要搭载的内容显得简单直接而富有价值(看目录其实可以抽看自己感兴趣的章节,似乎并不影响对前后文的理解)。抽空阅读下本书,无论是否使用 jQuery 都会对相关的知识面会有些帮助。

PS,由于时间差以及 jQuery 版本飞快增长的关系,推荐使用 1.6 版本,因为这个版本针对动画有所优化( 详细 )。

-- EOF --

可用性有如此重要?

请原谅我取了个如此有争议的标题,原文的标题是《浏览器不是什么》。我个人觉得作者有点脱离题目,但这并不影响其想要陈述的观点。

可用性 一直是我们前端争论的焦点之一。但仔细想想,我们是否值得为那些连见都没见到过的盲人阅读器或者那些自行禁用 JavaScript 的用户投入额外的、大量的开发成本去「满足」他们?

-- Split --

原文地址: http://blog.istvan-antal.ro/2010/10/what-is-not-a-browser/ 发声 。而后过了段时期,出现了能够同时使用扬声器和声卡的应用程序。

话说回来,现在是否还有人关心自己的机子上有无声卡吗?我想恐怕已经没有。甚至我觉得人们已经遗忘了机箱中的扬声器了。

例如,我从来没有见过某款游戏因为机子上没有声卡而自动关闭其声音--当然,如果我耳朵听不到那是另外回事情(老外的这个说法比较冷)。

说了那么多,上述故事和浏览器以及 JavaScript 的故事非常的相似。不同的是现在的开发人员,在开发应用的时候,仍然在考虑如果没有脚本支持的这一情况。

其实和当年的声卡普及情况差不多,JavaScript 发明于 1995 年(已经是 15 年前了)。当时其在浏览器中的份额不到 1%,而且当时的用户(甚至开发者)都认为这玩意是可有可无的。

我的观点是,每个 Web 应用程序应该能够尽可能的运行在不同环境中,但它并不说明无条件的迁就于某一情况,在任何情况下都表现一致。

例如,在浏览器没有 JavaScript 支持的情况下,新闻类站点仍然可以显示其主要内容(新闻),同时不保证那些依赖 JavaScript 的相册脚本,仍然还能正常工作。

我们现在称之为「浏览器」的应用程序必须为:它能理解 HTML、能使用 CSS 渲染页面、同时能驱动 JavaScript 脚本。某个应用程序只能够完成上述一项或者其中两项功能,那么这压根就无法称之为「浏览器」。

例如,搜索引擎理解 HTML(以及部分 CSS 防止作弊),我们只需要提供内容让其收录 -- 同时它不需要过多的了解 GUI 相关的设计。

从内容方面考虑,其实我只关心两件事物:搜索引擎和浏览器。首先,我第一步需要做的就是创建具有语义的 HTML(这对于 HTML 来说并不容易),然后再使用 CSS 排版并且使其支持现代浏览器,然后再使用 JavaScript 增加针对 IE 的 CSS 规则(很明显原作者非常讨厌 IE)。

我的上述工作流程有时候会收到指责,因为这样必须让老旧的浏览器具备 JavaScript 支持才能引入针对其自身的 CSS 规则。同时情况可能变得模棱两可,我真的不认为我们称之为「浏览器」的玩意竟然不支持 JavaScript,哪怕是那些可以称之为古董的玩意(暗指 IE 吗?)。

总而言之,我们的思路应该为未来而开发,而非迁就过去(We should develop for the future not for the past.)。

我们应该为大多数(用户)而非少数服务。如果我们的用户中有 0.1% 禁用了 JavaScript,那么在我看来,我们可能不值得去耗费大量的开发时间去争取那些 0.1% 的用户。

同时另一个事实是,如果我们让用户觉得在没有使用 JavaScript 的情况下也能使用我们的应用,那么他们会毫不犹豫的禁用它(类似 noscript 插件 )。那么这样,我们推进 Web 的前进几乎是不可能的,我们和用户都会认为 JavaScript 是额外的附属品。

最后,其实我想说明的是:在着手实际开发之前,我们首先规划那些有限的资源(例如时间、人力等)-- 它们的计划投入和实际产出是否能符合我们的预期。

-- EOF --

KISSY,重装上阵

面对繁杂的 JavaScript 库,其实到最后其实是 设计哲学的问题 。这篇文章将要介绍的是篇名为 KISSY 的 JavaScript 库。

渊源

前面也说过,JavaScript 库已经足够的多。可能看起来又要重新建立一套 JavaScript 库,有点重复造「轮子」的嫌疑,而 KISSY 的出现只是顺水推舟的结果。

过多的话语已经难以解释清楚 KISSY 的渊源, 这里有个详细的说明

风格

KISSY 的多数设计哲学源自 YUI3 ,同时也借鉴 了其他 JavaScript 库,我们可以看它的典型调用:

(function() {
    var S = KISSY, Y = YAHOO.util, Dom = Y.Dom,
        descList = S.DOM.children('#slideFocus ul.desc-list li');

    S.Slide('#slideFocus', {
        contentCls: 'pic-list',
        navCls: 'thumbs-list',
        activeTriggerCls: 'current',
        effect: 'scrollx',
        easing: YAHOO.util.Easing.easeOutStrong
    })
    .on('beforeSwitch', function(ev) {
        S.each(descList, function(desc, i) {
            desc.style.display = i === ev.toIndex ? 'block' : 'none';
        });
    });
})();

我们可以看到若隐若现的其他框架的风格,例如 jQuery 和 mootools,总之使用 KISSY 你会「重新找回书写 JavaScript 的快感」。

http://pic.yupoo.com/feelinglucky/8903298e1ebe/medium.jpg

(来自 BlueDream查看大图

从框架结构上说,KISSY 是相对精简的一套库,核心(core)非常的精炼。甚至你可以考虑基于 KISSY 扩展出适合自己的框架,例如针对 iPad 等等的特定库。

未来

KISSY 是开源项目,基于 MIT 协议发布。因此,KISSY 的未来掌握在广大开发者手中。相比目前现有的成熟的框架库,KISSY 还是个初生的新儿,因此尤其需要大家的支持。

目前 KISSY 已经部署到淘宝的大部分页面(包括首页),承受着不同浏览器以及大规模访 问量的考验。有理由相信 KISSY 能部署到更多的地方,让业界一起分享我们在前端方面的 心得和经验。

如果你有任何疑问,可以 访问 KISSY 的项目主页 ;同时官方站点、文档等方面也正在筹备和编写中。KISSY 的成长离不开广大同行的支持,我们的愿景是:

小巧灵活、简洁实用,使用起来让人感到愉悦

最后,感谢 玉伯 的努力,KISSY 的成长他付出了很多。

-- EOF --

Array.prototype 的泛型应用

在开始这篇文章之前,按照「惯例」我们先来道题目( 出处 )。

题目

请说明下面语句的输出:

x = {shift:[].shift};
x.shift();
console.info(x.length);

如果你回答正确,那么说明你已经了解 Array 函数的泛型应用。在理解这到题目之前,我 我们首先要了解数组(Array)的 shift 定义。

MDC 中已经对相关的说明 描述得非常的清楚

shift is intentionally generic; this method can be called or 
applied to objects resembling arrays. Objects which do not 
contain a length property reflecting the last in a series of 
consecutive, zero-based numerical properties may not behave 
in any meaningful manner.

同时,EMCAScript 中的定义也同时定义了对于 shift 操作对于对象 length 属性的改变, 那么基本上我们可以了解到上题中的答案为

0

扩散思维

如果对于上面的题目还无法理解,那么我们更清楚的说明 Array.prototype.shift 对对象 的 length 的影响。

x = {};
Array.prototype.shift.call(x);
console.info(x.length);

很明显,对于对象如果为定义 length 属性,则 shift 则会自动加上 length 属性并设置 为

既然已经说到这里,那么下面的题目输出什么留给大家去思考。

x = function (a, b, c) {};
Array.prototype.shift.call(x);
console.info(x.length);

重新认识泛型

很明显,上面的题目有可能还是无法说明本篇文章的题目。泛型(Generic)应用其实 期前也说明过 ,但这里主要说明 Array 方法 对于「类数组」的操作使用。

强制转换为数组

var args = Array.prototype.slice.call(arguments);

这个用法比较火星,其实期前也用过, 详细参见这里

迭代数据

Array.prototype.forEach.call(arguments, function(i) {
    console.info(i);
});

如果对象能够被递归,则出了「传统」的 for、while 等语句以外,还可以考虑使用 Array 的 forEach 属性(注意 IE 会是悲剧)。 Array 的 forEach 方法详见这里

其他的 Array 扩展用法可以散发自己的思维,如果对应浏览器的 Array 没有对应的实现方 法, 可以参见这里

其实,不仅仅是 Array 方法,很多浏览器原生对象的方法都是泛型,我们完全可以利用这 这些特性

  1. 使代码更为的清晰
  2. 使用原生方法,效率更高。

-- EOF --

What is "this"? - Part.2

好了,我们 继续上次留下的问题

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.
);

我们考虑语句 3. 和上面的两个语句有什么不同

(foo.bar = foo.bar)(), // 3.

相比语句 2.,语句 3. 中的 Grouping Operator 中有赋值(「=」)语句。那么,我们首先得明白赋值语句干了啥,继续 参考对应的 ECMA 文档

11.13.1 Simple Assignment (= )

The production 
    AssignmentExpression : LeftHandSideExpression = AssignmentExpression 

is evaluated as follows:

1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3.Call GetValue(Result(2)).
4.Call PutValue(Result(1), Result(3)).
5.Return Result(3).

其中,最重要的步骤就是 PutValue,我们 继续刨根问底

8.7.2 PutValue(V, W)

1. If Type(V) is not Reference, throw a 
   ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V) 
   for the property name and W for the value.
5. Return.
6. Call the [[Put]] method for the global object, passing 
   GetPropertyName(V) for the property name and W for the value.
7. Return.

所以,我们根据上面的定义可以得知,语句返回的是 foo.bar 的函数值。因此,赋值操作符返回的是「值(Value)」而不是「引用(Reference)」。

因为函数体需要 this 值获取 x 属性的值,那么接下来我们考虑改函数时调用时的上下文作用域以及背后的具体流程。 尤其注意第七条规则

...
6. If Type(Result(1)) is Reference, Result(6) is GetBase( Result(1)). 
    Otherwise, Result(6) is null.
7. If Result(6) is an activation object, Result(7) is null. Otherwise,
    Result(7) is the same as Result(6).
8. Call the [[Call]] method on Result(3), providing Result(7) as 
    the this value and providing the list Result(2) as the 
    argument values.
…

那么在这种情况下,GetBase 操作实际上返回的是 null,因此此条语句函数执行的作用域为 global ,在浏览器中也就是 window 。

(foo.bar = foo.bar)()

那么,上面的语句中我们可以得知

  1. Grouping Operator 中的赋值语句返回的是 foot.bar 的函数值(「Value」)
  2. 该函数执行的上下文作用域为 window

那么,在该函数中执行获取 this.x 也就是获取 window.x 的值。因此,这条语句返回的就是 10 。如果还不理解,考虑下面的代码段

var x = 10;
(function() {
    return this.x; // 这里会返回什么?
})();

如果理解了上面的语句的前因后果,那么题目中的语句 4. 就能举一反三给推导出来。首先我们来了解逗号运算符(「,」)的定义,我们就可以得之语句

(foo.bar, foo.bar)

返回的也是 foo.bar 的值「Value」而非引用「Reference」,那么接下来的事情其实就是和语句 3. 一样的了。因此,语句 4. 返回的液是 window.x 的值,也就是 10 。

总结下,那么上面的输出总的来说是

20 20 10 10

-- Split --

似乎目前为止,我们已经完全回答出了当初设定的问题。但恐怕会留下疑虑,就是传值「Value」和引用「Reference」之间到低有何不同、函数的作用域以及 this 的指向是否已经真正了解?

是的,这个题目已经完了,而我们的问题似乎还是没有怎麽搞清楚。OK,下次我们来详细讨论下这个问题…

-- To be continued --

我的照片

嗨!我叫「明城」,八零后、技术男、伪苹果粉、微软无脑黑、宁波佬,现居杭州。

除了我的博客,同时也欢迎您访问我的 GitHubTwitterInstagram 主页。

这个 Blog 原先的名字叫 Gracecode.com 、现在叫 「無標題文檔」 。 其实无所谓叫什么名字,因为我曾经为这个名字伤透了脑筋。最后想到的这个名字都没啥特别的,说到 底是因为我实在给它不了个非常酷的名字。

如果您想联系我,可以发我邮件 echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d

文章

项目

微信公众号