Tagged: javascript RSS

  • tin 1:59 am on January 13, 2010 Permalink | Reply
    Tags: api, javascript, , pattern-matching, style   

    Reply lifesinger’s blog post: jQuery 让人恋恋不舍的秘密

    是pattern matching,基于消息的函数调用经常使用这样的模式。因为jQuery的functional风格,所以它使用了pattern matching来收紧api数量,效果很不错。

    但是上次mootools的开发者说过jQuery的这种设计也意外的鼓励了一次使用就抛弃的代码风格,容易造成你写只为一个页面而作的代码段。这对于鼓励前端开发减少代码重复不利,从长期来看,由于js还不支持原生的pattern matching,所以jQuery这种方式也能由于api灵活降低一些代码的可读性。

     
  • tin 9:12 am on December 9, 2009 Permalink | Reply
    Tags: javascript   

    今天被身边的众神拉出来一个很二的bug,发现javascript里面

    parseInt('09') = 0

    所以需要

    '09' * 1 = 9; '09'-0 = 9; new Number('09') = 9

    太生疏了

     
  • tin 3:34 am on September 6, 2009 Permalink | Reply
    Tags: javascript, , , patterns, , programming to patterns   

    Javascript库的“实现模式编程(Programming to patterns)” 

    今天看到了一篇很好的讲Javascript Library的文章:http://www.clientcide.com/best-practices/jquery-and-the-ajax-experience-programming-to-the-pattern-and-what-really-makes-one-framework-different-from-another/
    作者是一位MooTools开发者,他写了对实现模式编程(programming to the patterns)进行了阐述。告诉我们像Prototype、MooTools这样模拟类继承并鼓励使用OO的方式组织你的代码对于你的好处。而对比的对象就是红火的JQuery。他的观点我举双手双脚同意。

    JS的通用库最基本的目的是给你解决浏览器兼容性差异,让你在与浏览器兼容性的战争中给你一个巨大的后援保证。但是只提供浏览器兼容性的JS库是不会流行的,你还需要在编程模式和代码效率(Code efficiency)上提供帮助。对于我个人来讲,对语言的流畅性改造最好的就是Prototype这个库,因为它营造了一个“最小惊讶”的Ruby语言环境,让你几乎感觉到是在编写流畅的Ruby,尤其在Rails项目里面使用更让你感觉到Ruby和Javascript结合的流畅。(此处我想到了上周Cat Chen同学和我提起的“Language Oriented Programming”的概念,也许这就是它的表现吧,扩展语言减小编程中的“惊讶”)相比之下JQuery则在代码效率上做了很大功夫,这个代码效率不是指运行速度,而是单位代码完成的功能。JQuery对Dom的DSL化封装,还有对method chain的大量使用,几乎让你感觉在声明行为,所以它让非常多的对啰嗦的Dom编程厌烦的前端程序员迅速“上瘾”。但是,我们知道DSL化的JQuery还不够,因为它很好的解决了可读,但是并不一定容易维护(尤其是过度使用method chaning)。另外一个原因就是习惯使用“声明化”以后会让一些程序员忘记“抽象”和“封装”,很多JQuery都没有使用面向对象OO的方式去组织自己的代码,而是拥抱了面向过程编程,而很多人却还自我安慰说自己使用的是“函数式编程”。如果你没有做好函数抽象,那么绝大多数情况下你的JQuery code都不符合函数式编程的本意,此时你也就离抽象出可复用的“模式”越来越远了。

    其实JQuery的很多UI plugins是很好的例子,尤其是支持Progressive Enhancement的JQuery UI插件,它们都很好的规定了自己的micro formats,然后根据dom的模式来组织自己的行为模式(Behavior and Patterns)。它们才是很好的对实现模式编程(programming to the patterns)的例子。缺少了对模式的抽象也就失去了在大的项目中实现代码效率(Code efficiency)的优势(因为代码复用度会下降),这对于JQuery这样一个以“Write less, Do more”为口号的库来说就失去了它最大的卖点。

    所以,实际上关键的问题就是,用哪个JS库都没错,但是如何使用和形成模式才是关键。每个库组织自己的“模式化代码”的风格不一样。但是像MooTools和Prototype(还有YUI)这类基于类去组织代码的库的源代码本身就已经告诉了你如何组织你的代码,而且它们的OO实现对于任何一个熟悉OO的程序员来说都“没有惊讶”,那么你就很容易吸取他们所推荐的代码组织风格了。

    最开始所引用的文章归纳了几个不面向“模式”组织代码的坏处:

    • 缺少抽象,缺少复用
    • 会形成零散的代码,修改起来成本会比较高,维护成本也就增高了
    • 不OO,不容易组织扩展

    我补充一点:

    • 过程化的代码不容易测试,不使用模式的代码也会造成测试的零散,造成浪费

    更新:有一点不准确,就是关于复用,其实Javascript的各种Widget库(如ExtJS、Dojo和YUI的widget库)都做到更好的复用。缺点是目前的widget库中的高级控件都严重的绑架了Dom结构,造成自己修改Dom结构比较麻烦。而没有使用Micro Formats这样的基于标准的弱耦合,这是一个很大的问题。所以由于这样的实现绑架的问题,这些Widget库不包括在上面所述的框架对比中。

     
  • tin 10:07 am on September 26, 2008 Permalink | Reply
    Tags: javascript   

    关于javascript库的一个回复 

    我以前写过一篇说说我对moo、prototype、JQuery的看法在我的blogjava博客里面(现在我已经不更新了,完全使用这个wordpress的博客)。今天也是在Google Reader里面看到JavaEye的另外一个朋友lifesinger的一篇文章:大胆预测下几个JS框架的走势,我个人不是非常同意,所以写了如下回复,也发在我的blog吧。

    完全不同意lifesinger的说法:

    1、JQuery会走的比较远。因为Django会走的比较远。而且JQuery的内部设计很好,如果说它不好估计是没有理解它的核心理念。而且John Resig的确是个勤奋的福音传播者,它的js使用理念很好,所以这个库会随着它的plugins库的数量质量的双重提高,占重要位置。同时浏览器效率的的提高也会给它注上强心剂。

    2、YUI的api设计不好。作为oo的库它不好,作为fp的库它更不好,所以它不会有多好。不过在widget类库里面它肯定继续占重要地位,因为YUI的widget的确兼容性很好。

    3、moo我很喜欢,但是它的演化保持了小众的特点,小步前进,api设计上比较偏设计师的想法。做大型项目的时候你回发现moo没有对如何组织你的项目给很好的“风格”上的建议,所以它也就会在大型项目上哑火。

    4、Ext,我看没什么大的希望了。因为它的授权问题,基本上它已经不在是开源社区友好的(它也许可以做自由软件社区友好吧)。而且作为一个UI Widget库,它并没有把可访问性放在重要的地方来重视,所以随着UI的可访问性要求的上升,它的默认皮肤带来的eyecandy估计就没法盖过usability的缺失了。

    你没有提到Prototype,它目前还是js lib的第一名,随着活跃的RoR社区的继续推进,它应该还会持续足够的市场份额。而且它和JQuery同属于有强烈“风格”的库,所以即使项目很大,它还可以保证代码的可读性与可维护性,这对于很多项目来说是至关重要的。

    关于dojo我不说了,以前说过:说说我对moo、prototype、JQuery的看法的回复里面有。

     
  • tin 1:53 pm on August 19, 2008 Permalink | Reply
    Tags: javascript, ,   

    关于Javascript的入门图书 

    犀牛书绝对的过时,也绝对的不友好。在开始的时候,作为一本系统讲解javascript的书,它非常注重阐述规范,所以在那个时代它是最好的图书。但是现在,作为js技术的入门图书,我们有一些更好的从javascript的精髓和基本理念入手的图书,读完他们你就可以体会到规范为什么是这个样子,从记忆角度来说理解后的记忆要强过死记硬背,所以用这些图书入门是更好的选择。

    Update: 有位Sina的同事说道犀牛书还是要有一本的,目的是作为参考书。我倒是觉得这个完全可以依靠网络,因为大部分时候我们就是想索引一下方法,或者看看方法签名和解释,这个时候通过在线服务绝对要好过翻书。服务里面gotapi是个不错的选择!

    在国内看翻译的推荐看:

    1、大辫子nicholas写的Javascript高级程序设计

    2、John Resig写的精通Javascript (Pro javascript)

    ppk on javascript这本书也不错,比较实用,但是个人感觉没有精通Javascriptt这本讲的清楚。

    如果看原文可以期待:

    1、John Resig的Javascript Ninja,未出版,但是有样章。

    2、Js大神Douglas Crockford的Javascript The good parts.

    上周和钱钱讨论Programming Ruby这本书的时候我们也持这个观点,它曾经是一本非常棒的入门书,因为那个时候它是第一本非日文的Ruby图书。但是这本经典书到了现在已经有了很多不一样的竞争者,像钱钱同学推荐的Every day scripting with ruby就更偏实践,更容易让你入ruby的门。

     
  • tin 10:10 am on July 22, 2008 Permalink | Reply
    Tags: javascript,   

    短小精悍的Javascript模板引擎 

    今天看到Jonh Resig的博客里面提到了他在他的Secrets of the JavaScript Ninja这本书里面介绍的一种简单的模板,代码如下:

    // Simple JavaScript Templating
    // John Resig - http://ejohn.org/ - MIT Licensed
    (function(){
    var cache = {};

    this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
    cache[str] = cache[str] ||
    tmpl(document.getElementById(str).innerHTML) :

    // Generate a reusable function that will serve as a template
    // generator (and which will be cached).
    new Function("obj",
    "var p=[],print=function(){p.push.apply(p,arguments);};" +

    // Introduce the data as local variables using with(){}
    "with(obj){p.push('" +

    // Convert the template into pure JavaScript
    str
    .replace(/[\r\t\n]/g, " ")
    .split("<%").join("\t")
    .replace(/((^|%>)[^\t]*)'/g, "$1\r")
    .replace(/\t=(.*?)%>/g, "',$1,'")
    .split("\t").join("');")
    .split("%>").join("p.push('")
    .split("\r").join("\\'")
    + "');}return p.join('');");

    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
    };
    })();

    这段代码非常简单,但是却有不少trick。而且这些trick十分的优雅(John resig一向擅长写优雅的javascript)。非常值得读一下。思路就是把一段模板引擎里面的求值代码标记出来,将其余代码用单引号包裹起来,所以代码会分为文本和求值两种部分,压入一个Array,最后join。把这个逻辑用string的形式初始化一个Function对象,然后cache起来就成为一个高效的javascript模板引擎了。不过这个引擎只有求值赋值的功能,没有更加复杂的逻辑控制如if, else, for这些循环,但是在求值部分增加一些正则判断来处理这部分逻辑也是可行的。我非常喜欢的Trimpath Javascript Template估计也是这个思路(虽然经常用,但是由于代码可读性的问题一直没有仔细阅读它的源码)。

    这段代码里面的闭包用法也很不错,可以防止命名冲突和全局变量的污染,不过这个写法估计大家都比较熟悉了。

    模板的用法就不赘述了,如果你想用这个微型模板可以看看John Resig的JavaScript Micro-Templating

     
  • tin 12:11 am on April 15, 2008 Permalink | Reply
    Tags: CI, , firefox, javascript, , , , , 持续集成   

    在Mac下启动多个Firefox实例方便JsUnit运行 

    项目中的JsUnit是使用ant脚本运行的,里面需要设置BROWSER_PATH的环境变量来启动浏览器。在本地check in代码的时候,我们会运行一下测试来减少愚蠢错误被提交到代码控制系统。但是在我的mac下Firefox只能启动一个实例,在运行JsUnit test的时候会提醒我已经打开了Firefox,不能打开另外一个实例,这样我必须关闭正在运行的Firefox。而且由于我比较喜欢打开非常多的Tabs来保持浏览状态,所以关闭Firefox让我很不爽,再说,因为重新启动的Firefox里面带了很多的Tabs,所以经常造成实际运行的JsUnit test发生随机性的超时错误,这个就不能容忍了,因为这无法保证我们的信心。

    那么,为什么FF不能启动多个实例呢?原因是它们共享同一个Firefox的profile,所以没法多个实例并发访问。但是通过命令行参数是可以创建多个profile给firefox的,简单了。不过遇到的问题是JsUnit的ant任务会检测BROWSER_PATH是否存在,所以如果我把带参数的命令行写到环境变量里面Ant无法检测到这个文件就会报错。那么如果关闭检测可以么?还是不行。因为JsUnit的StandaloneTest里面实际最后会调用DefaultProcessStarter的execute方法,这个方法调用Runtime.getRuntime().exec(command),这个实现非常直接,不过因为parameters如果直接写到命令行里会发生文件无法找到的问题(应该用数组将命令和参数传入)所以没有办法传入,还是无法运行。

    放弃hack吧,我可以修改Ant task和JsUnit的方法,但是绝对不好,因为这个hack没有提交回去的意义。
    所以换个思路,这样做:我们去写个shell来解决它。

    先在终端运行/Applications/Firefox.app/Contents/MacOS/firefox-bin -CreateProfile jsunit,这时候会弹出窗口让你确认创建这个profile,选择一下不使用extensions和各种工具条,这样减少这些设置对测试的不良影响。
    然后在你的home目录创建一个firefox.sh,里面写上:

    /Applications/Firefox.app/Contents/MacOS/firefox-bin -P jsunit $1

    前提是你的Mac使用的是默认的bash,否则修改$1为对应的引用字符。然后chmod firefox.sh 555,让它可以运行。

    下面就是修改你的~/.profile:

    export BROWSER_PATH=/Users/[User path]/firefox.sh

    source ~/.profile让修改生效再运行JsUnit就OK啦。如法炮制想开几个Firefox实例都可以啦。同样方法也适用于让Firefox2和Firefox3共同运行!非常简单。还可以做到开发和浏览分开……以此类推。

    回顾一下JsUnit的代码写的不好,如果像Selenium一样能够自动创建一个profile就好了,因为那样可以减少测试之间的影响,还可以让Selenium并行执行。我想,如果有空我可以做一下这个工作:D

     
  • tin 9:27 am on April 8, 2008 Permalink | Reply
    Tags: javascript,   

    Yahoo的“前端优化突破” slide共享 

    这是一篇很好的讲前端页面优化的slide,当然有不少内容我们都看过很多遍了,我以前做过的:

    里面的内容也有一些重复。不过这次我还是很有收获,比如IBM的Page detailer就是个不错的profiler工具。还有使用document.getElementsByTagName(‘*’).length简单判断dom复杂度的方法也是不错的。结果是:

    • 新浪首页是3109
    • 财经首页是4260
    • 新浪邮箱是169
    • 纸条箱251
    • sohu是2k4
    • netease是1k4

    很有意思。

    结绳记事。

     
  • tin 7:55 am on January 31, 2008 Permalink | Reply
    Tags: javascript, , ,   

    写javascript单元测试是挺爽的事,可惜不要在safari上? 

    对于javascript来说,通过单元测试,你也可以实现TDD。对你非常有好处,一是减少了js变动带来的代码退化问题,另外一方面是TDD可以改变你设计程序的方式。
    举个简单的例子,写javascript很多情况下是和BOM(也就是文档模型)和DOM打交道的,这样可以说javascript程序很容易与dom高度耦合,这样的程序运行起来没有问题,但是应对需求变化的能力会比较地。但是根据人的思维方式,javascript很多时候是先出页面,然后根据页面逐渐调试着写出javascript,对于开发者来说,脑子里并不是真正的清楚自己要什么,而是在想界面的结果……这样产生的高耦合代码不容易测试,也难以面对多变的界面。
    所以,换一种方式思考。如果用单元测试的方式去写,你就需要考虑程序的可测试性,这会细化你的程序的模块粒度,因为细粒度的抽象容易单元测试。同时由于js单元测试的页面是mock出来的,所以一般都会尽量的简单,这样会减少程序远对界面的依赖。同时由于界面的可测是性问题,也许会减少对element的style的修改,转而使用语义话的css。例如如果一个元素高亮,你可以element.style['font-size']=’bold’;element.style.color=’red’l….,当然你也可以element.addClassName(‘highlight’),然后那些不好验证的界面的约束条件可以放到css里面去,放给可用性和用户验收测试去验证。这样的单元测试的验证条件(assertion)会简单很多,如果写过单元测试的朋友肯定会有感触的。
    那么,常见的Javascript的单元测试框架有JsUnit和scrit.aculo.us的单元测试框架两个。前者方便用ant调用和分析结果,适合使用了ant的项目。而后者的优点就是界面好看,直接运行产生的报告清楚漂亮。所以小型项目我倾向后者,而大型项目我倾向前者。当然,由于js的动态特性,其实做个单元测试框架非常简单,所以自己动手也无妨。关键是要写,而且争取做到测试先行。

    前面是个引子,其实写这个的原因是今天上午的一个郁闷的事。
    前面的blog entry说道我升级了Firefox3,结果遇到了getElementsByClassName问题。但是今天换到另外一个项目组,没有用那个方法,程序也正常。可是我TDD的写一个新的feature的时候却发现可爱的JsUnit的testRunner在Firefox3里面无法工作,从firebug里面看到了一堆安全性问题。估计是firefox3的新安全模型造成的吧。那么,由于firefox3覆盖了firefox2,所以难道我没法写程序了?当然不可以,还有safari嘛。马上开始去写测试了,写好测试执行测试,发现红条。嗯,很满意,因为TDD的红-绿-红-绿的节奏就是这样的。然后我开始去写实现来满足这个测试……结果忙活了一上午就是不行……而且发现一些原来的测试也无法通过了……我仔细寻找问题,diff修改的内容,可是最后实在没有发现任何让它不能通过的原因,因为手工在firebug里面都已经验证了写的实现是没有问题的呀……崩溃。此时我突然想起来我们的持续集成服务器里面没有跑safari的JsUnit测试……也就是说不能确定在safari下全绿(此时的背景是我们的持续集成显示全部绿色,也就是说所有的测试都可以同过,包括windows和linux平台还有IE及Firefox),那么我可能衰了。马上开动camino(靠,一上午都忘记用它执行JsUnit了,因为我的习惯是Camino里面保存to read list),运行一下全绿。很兴奋,但是感觉刚才寻找问题的1个多小时被无辜的浪费了,心疼呀。

    那么,请注意啦,我只是想提醒,jsUnit可能不能在safari下正常工作(大部分测试没有问题,少量在其它浏览器正常的测试在safari下无法工作),我用的是safari3.0.4……

     
  • tin 7:19 am on January 31, 2008 Permalink | Reply
    Tags: javascript, , Prototype   

    Firefox3 beta2带来的getElementsByClassName问题 

    Firefox3解决了一些内存泄露问题,或者说主要的是解决了一些长时间运行以后的内存占用问题。由于使用mac的习惯是休眠不关机,所还是在正式版出来之前选择了升级到firefox beta2。
    那么作为开发人员肯定遇到firebug不能用的问题,还好,我们可以用firebug的beta版本来解决这个问题,当然这个firebug还是会出现莫名其妙的问题,无所谓啦,不久就会发布正式版本了。
    这些都是废话,问题集中在firefox beta2提供了原生的getElementsByClassName方法,而我们大家都很愿意使用的prototype库正巧也给Element封装过getElementsByClassName方法,看起来两者的作用是一样的,但是不巧……其实两者还是有很大差别的,所以造成了如果你的项目正巧用了getElementsByClassName方法,而后你又用习惯的prototype方式便利了它……那么你的程序就不能在Firefox3 beta2工作了……
    我们以前的习惯就是不用考虑新浏览器的javascript兼容行问题,只需要考虑向后兼容,但是这次问题还是出现了变化。
    其实原因是简单的:
    1、Firefox3实现的原生getElementsByClassName方法返回的不是javascript数组(Array),而是html element collection,这个东西可以用标准的方式遍历,但是却与Array没有共同的prototype(这个指javascript里面的原型继承的prototype)。所以,很不幸,如果你用了Prototype库的那个返回Array的方法写程序,然后使用了Array增强方法里面的first()等方法或者Emmerable里面的each()等方法,那么程序一定会出错。此时你可以$A一下这个html element collection,但是这不是好方法。因为其实Prototype在1.6以后就不推荐使用getElementsByClassName方法了。
    2、那么解决的方法就是使用select方法代替原来的getElementsByClassName方法,不过记得要给参数的前面加个”.”。比如oneElement.getElementsByClassName(’someClass’)应该修改为oneElement.select(‘.someClass’)。而其实select方法由于接受css selector语法,可以实现更强大的选择操作。

    嗯,非常废话。
    那么简单的说:如果你在Firefox3里面发现你的基于Prototype库的js程序的getElementsByClassName以后出现了method null的错误,那么你需要用select方法代替它。且考虑到长时间的不兼容状态,最好完全消除你的程序中的getElementsByClassName同名方法调用,不关你用什么js库。

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel