jQuery 为什么优秀兼谈库与框架的设计 #114

Open
lifesinger opened this Issue Feb 20, 2013 · 68 comments

Comments

Projects
None yet
Owner

lifesinger commented Feb 20, 2013

@wintercn 的这篇文章说起:从 jQuery 谈库与框架的设计之优劣

先去读一读哦,不长的,winter 写得很幽默。

好了,看下文。

解决什么问题

拿 winter 的代码入手:

function traversal(node, f) {
    f(node);
    if(node.children.length) {
        for(var i = 0; i<node.children.length;i++)
            traversal(node.children[i],f);
    }
}

traversal(document.body,function(element){
    if(element.tagName=="button" && element.className.match(/continue/)) {
        element.innerHTML = "Next Step...";
    }
})

这段代码很酷,看见了递归没?还有传说中的函数式编程!也不长,只有 166 个字符。考虑 jQuery 那庞大的 97K 代码,完全可以自己写啊,真心用不着什么类库。

可是,各位看官,在中国,有两种东西需要小心:一是 CCAV 的新闻,二是程序员的代码。你信前者就幸福了,后者嘛,请看:

尼玛,winter 坑我,复制过来的 traversal 方法工作有点不正常呀

为了节约笔墨(精彩在后面),先不说 children 的坑(不说是因为 winter 刚好绕过去了),来说说下面这个:

<button class="continued">

这可不是故意挑刺,我们在讨论类库哦。上面的 button 也会被 traversal 命中。好吧,我帮 winter 修改下:

traversal(document.body,function(element){
    if(element.tagName=="button" && element.className.match(/(?:^|\s)continue(?:\s|$)/)) {
        element.innerHTML = "Next Step...";
    }
})

修改后,正则看起来很酷。师兄下次 review 代码时,应该会觉得我技术有进步,加薪、晋升有望了……

继续节约笔墨(精彩在后面),不说代码的优化空间。只想问呀,这么一个简单的功能,值得如此折腾吗?为何不用一行搞定:

$( "button.continue" ).html( "Next Step..." )

好了,各位看官,你还同意 winter 说的 jQuery 是 “没有问题创造问题也要解决问题” 吗?

调侃结束,言归正传。jQuery 解决什么问题,jQuery 能做什么,来看官网:

jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.

云译一下:

jQuery …… 让 DOM 操作简单 …… 跨浏览器 ……

翻译有直译、意译、神译,但在云时代,得用云译。诠释如下:

  • jQuery 是 DOM 操作类库,非常专注。 这很重要很重要。正是这种 专注做小 的心态,让 jQuery 在 DOM 操作领域所向披靡。这比野心勃勃想着做大的 Prototype、YUI、Dojo 等不知强多少呢。jQuery 的流行证明了专注的力量。找老公也可以用 jQuery 去衡量。
  • jQuery 真的很专注。 常见的 each,尼玛的 Deferred 等看起来和 DOM 无关的东东,实际上跟 DOM 方法的实现很有关系,暴露出来挺有用,因此才暴露。此外,与 DOM 操作实现无关的 cookielocalStorage 等等,jQuery 一律不提供。(注:个人觉得如果这些内部方法不暴露,只暴露与 DOM 操作相关的方法,jQuery 会更完美。注2:别跟我较真说动画和 Ajax 不是 DOM 操作。)
  • jQuery 非常关注用户。专注于 DOM 操作及其兼容性,让普通用户包括设计师都可以快速写出代码,这是 jQuery 的巨大价值。

预测:苏宁电器会改名叫苏宁云商,但 jQuery 不会改名为 jLibrary。和 jQuery 同样专注的还有 Evernote、Amazon、Dropbox 等等牛逼的东东。

(精彩已讲完,下面可以不看。 在类库界,解决了 What,解决了定位问题后,基本上已经决定了生死存亡。 至于 How,也重要但往往不是关键。最近看 Grunt 类库,也有同感。)

也谈命名

命名非常重要。比如决定 winter 牛逼的,不是 1024,而是 winter 这个名字。

不过没看懂 winter 说什么,因为 winter 说的和 jQuery 没什么关系。可能跟 jQuery 的早期版本有关系,但任何事物都会有历史局限性,就如我就一直期待传送门,但不能嘲讽当代的汽车。

至于 $ 的选择,这就如 码农屌丝 等词汇一样,winter 好像也经常用,并不反感。$ 的选择也像 QWERT 键盘,或者系统中用 ~ 表示 Home 目录一样。为什么很少见 *nix 用户不爽 ~ 呢?

不评论了。要谈命名,不如谈 jQuery 的方法名,简洁明了。YUI3 等类库抄得不亦乐乎,这是一种认可与致敬。

接口设计

泛义上讲,完全同意 winter 的说法。我也非常讨厌一个方法职责不清、身兼数职。比如 RequireJS 里,最让我不能忍受的重要原因之一就是,天杀的 require 方法一会是全局方法,一会是函数变量,一会是云,一会是风……

不过, 谈任何设计,都离不开场景。

jQuery 是 DOM 操作类库。jQuery 首要要解决的是: 如何高效方便地操作 DOM? 在这个真实需求下,jQuery 选择了一句话:

找到 DOM 元素,然后再操作、继续操作。

上面这句话,不是 jQuery 凭空设计出来的,而是千万前端工程师们在写代码时实际上会干的事情:

var foo = document.getElementById("foo");

foo.setAttribute("data-bar", "bar");
foo.innerHTML = "...";

上面的代码挺不错的,但有坑。jQuery 将上面这种常见代码,通过链式操作简化成了:

$("#foo").attr("data-bar", "bar").html("...");

这就如我们一般不会说:

我是 winter
我喜欢编码
我喜欢妹子

而会说:

我是 winter,喜欢编码,也喜欢妹子。

至于 getter 和 setter 的统一,可以类比:

var host = { a: "a" };

// 获取值
alert(host.a);

// 设置值
host.a = "aa";

别跟我说一定要:

var host = {
  a: "a",
  getA: function() { return this.a; },
  setA: function(val) { this.a = val; }
}

不直接通过属性,而通过方法来搞定 getter 和 setter,个中缘由 winter 比我更清楚,有兴趣的可以看:defineProperty

其实上面说的跟 winter 反驳的没什么关系,winter 主要反对职责不单一。不过,职责不单一的方法,在 jQuery 里有,但并不多。至于 $ 的功能,这是入口方法,为了用户的便利性, 适当放下程序员的完美情节,个人觉得是一种 面向用户的权衡。很多产品也如此,在屌丝用户看来很糟糕,但普通用户还真喜欢,因为方便。

耦合

举例子来说说:

  1. YUI3 最初的理念中,有一个很重要的是 颗粒化。颗粒化使得 winter 可以单独调用 ajax 模块。然而,YUI3 发展至今,虽然颗粒化极细,但你若去看使用 YUI3 的页面,稍稍 YUI().use("node") 一下,加载过来的文件大小就超过 jQuery 了。
  2. 颗粒化必须考虑颗粒的大小、范畴。 在 DOM 操作领域,能够保持功能与 jQuery 近似,大小又比 jQuery 小的,目前我好像还从来没有看到过。除非把定位缩小,比如只支持 webkit,砍功能后,才有可能比 jQuery 更小。同等功能下,能做到 jQuery 这么优秀的 DOM 操作类库,如果你发现了一定要告诉我。
  3. 一个文件。 能用一个文件解决的,不用两个文件来做。超过一个文件就意味着依赖关系的管理。这里拿老赵的 Wind.js 来说,够屌丝了,但普通用户真不愿意去搞清楚那几个文件怎么引,还要分谁先谁后,天哪。所以后来 Wind.js 也有了 aio 版本(All in One)。方便用户,而不是满足自己。
  4. 历史与未来。 当然,上面说了这么多,但场景在飞速变化。比如 IE6 的市场份额在国外已经到了可以忽略的地步。场景的变化,使得 jQuery 开始朝向 2.0 发展。Animation 和 Ajax 等模块在设想中也都可以独立出来,还有很多很多变化。但最大的变化,个人觉得不是理念更先进了(模块化老掉牙了),而是 顺势而为。这个“势”是场景的变化。设计架构的演变,离不开场景。场景的变化经常推动着设计的进化。很多公司的架构之所以牛,并非牛人使然,而是公司业务场景的需要。快跑题了,这个另一个蛮有意思的话题……

写在最后

jQuery 的专注,不三心二意, 非常有利于生态圈的形成。君不见,jQuery 社区目前就是前端界的阿里巴巴呀,winter 你来一淘了,应该认可阿里的大方向哦。反观 YUI3 等框架,不是京东又是什么呢?

最后,来点煽情的。jQuery 在我心中,是一尊女神。她温柔、细腻,她火辣、傲娇,一定会有人骂她,但真了解她的,会爱上她。

zhanghua

(全文完)

chaozh commented Feb 21, 2013

从个人感觉jquery的API设计确实很牛逼,自己写过类库就会发现职责过多的类库实际一点用都没有。另外jquery的动画目前看来确实可以考虑以插件形式发布了,但是又有兼容性的问题,骑虎难下咯。

凑个热闹。。。

感受&学习~

jq的api不的不说很帅气,不过jq的文件是越来越大了。。

还记得那个人说的一句话,不用jQuery的原因是:它抹杀掉了程序的“本质”。--> 囧。

@Johnqing 可能是还要兼容IE6+这些吧,一旦丢掉这些包袱,体积应该会降低很多的。

感觉winter从单一的案列上去分析了jquery 其实这类大量使用的类库肯定需要满足很多匪夷所思的情况 单一的是给自己用的 众口难调加上为了考虑到各方各面 所以winter看jquery复杂臃肿 其实到是像玉伯之前说的这是一个加法和减法的问题

winter老师并未了解jq为什么那么“流行”,因为他觉得他那样的开发者(甚至国内很多“大牛”)可以轻松写出那种比较“烂”的代码(文章中也讽刺了),却忽略了jq并不是在创造问题,而是事无巨细。winter老师讲jq的一些设计很“烂”,很容易被一些初级开发者误读为“用jq这种行为很烂”
不过事实上大家都懂的,国内对前端界的贡献只是九牛一毛,但很多人还特喜欢输出。。

学习之~

edokeh commented Feb 21, 2013

用了 zepto 之后,才知道 jQuery 是多么的贴心
不信的话看看这段代码 https://github.com/jquery/jquery/blob/master/src/attributes.js#L380
你们感受下~

高富帅不懂屌丝的痛 :)

sapjax commented Feb 21, 2013

winter老师如果深入到基层,多做一些业务开发,以使用者的身份去体会,而不是框架设计者的角度去看,可能会有不一样的想法。

任何框架都有它的利于弊,jQuey的给95%以上的开发者带来了便利,不必为了那5%像Winter老师那样的神级开发者而否定它吧。

wiky commented Feb 21, 2013

感受到一缕缕浓浓的爱意。。。

最后一句话,很文艺范,原来code跟文学是一样的......

只是工具而已,无从优劣之分

jquery体积倒是越来越大了,也看到在砍过期功能了,这是个用的很爽的库,除了体积稍微有点大。

winter颇有点解构的意思,嘲弄权威。其实和玉伯关注的是两个方向,温拿就像顶级狙击手,而玉伯则是独立团团长。

用心地读完了两篇,首先感谢作者。说说一个从1.2.1版本开始接触jq人的一些感受:首先理解了“框架”和“库”的区别之后,我们再来看,站在一定高度来审视它远比简单机械地使用它而言,更深入、彻底。没有完美的东西,项目开发有的时候更多地考虑成本相关。jq一路走来,追随它久了,也会厌倦和bs它的部分不足。但是我们可以做的,普及它,提升“初中级使用者”的内在素质技能,脱离平庸的“user”,建议很多用过、骂过、爱过jq、抽取jq部分设计思想、超越过jq的种种人多多比较一下版本迭代的api设计区别,细化框架设计的本身内在更能让你认知jq

cssrain commented Feb 21, 2013

给自己写类库和给其他人写类库的区别。

Jq对于像我这样的入门级 非常受用。何必纠结于代码的原生。

jizhang commented Feb 21, 2013

我们这边基本上写JS就等于写JQ了。很赞同玉伯的观点,凡事要看场景,以及面向用户的权衡。97K么……现在网速那么快,CDN那么普遍,浏览器又那么牛X,不怕了。

ksky521 commented Feb 21, 2013

占位

俺也占位吧

yaway commented Feb 21, 2013

还处在用JQ烂代码的阶段..但正是JQ这类的发明 给了菜鸟们一个 从不懂code到能很快开始写点东西 的机会..感谢JQ

ibigbug commented Feb 21, 2013

留名。国内前端界大事记。
这次讨论又让我想起了玉伯上次发起的编辑器 vs IDE的讨论。
个人使用经历来看,jQuery对于实现功能效果来说确实方便。不过一两个小功能,能自己用几行代码搞定的,我绝对不会去引入jQuery。

我是打酱油的!

两位都说的很好,玉伯老师很幽默。。。其实不用争论那么多,事实已经说明了一切。正因为jQuery的专注、快速,对于屌丝程序员的吸引才那么大。jQuery得用户量,社区规模已经说明了她的优秀蕴涵在骨子里。

booles commented Feb 21, 2013

打酱油!

q13 commented Feb 21, 2013

屌丝前端正忙着堆页面呢,哪有时间考虑这些东西,怎么快速搭建怎么来。还有我理解的屌丝不是“低级”的代名词,是一种生活方式而不是技能定位。

iworm commented Feb 21, 2013

不用jQuery,只能使技术不太行的程序员写出比较糟糕的js,尤其是部分js只能运行于IE。而用了jQuery之后,可以在很大程度上改善这个现象。
现在在我们的遗留代码中还能看到诸如

while(node.parent.tagName != "tr"){
    node = node.parent;
}

这样的写法。这个用jQuery写起来不是很方便,而且很有语义的事情吗。

zensh commented Feb 21, 2013

“不直接通过属性,而通过方法来搞定 getter 和 setter”,新手求教

漂亮

学习之!

看了那文章和玉伯的文章,还有些地方不明白,看来自己还是努力啊,呵呵

loethen commented Feb 22, 2013

jquery节省了开发时间,解决bug的时间,挺好用的。

zhouhao commented Feb 22, 2013

jQuery很美,支持JQ

biqing commented Feb 22, 2013

两位从不同角度为大家呈现了jq的不同侧面, jq确实存在不少历史因素, 导致其作为优秀类库但仍存在一些设计不合理的地方.
从这几年的发展来看jq的方向是良好的, 全球使用jq的站点太多了, 这种牵一发动其身的改进也必然要慢慢来的.

EchoFUN commented Feb 22, 2013

基情四射。

mrhack commented Feb 22, 2013

玉伯说的场景不错,如果一个你只因要实现一个功能,而引入一个jquery,实在不值。但如果你需要实现大量的dom操作,而引入jquery并不是一件很不光彩的事

关于yui部分的说法,有些不对哦

YUI3中,node是一个由十几个子模块rollup而成,以3.7.2为例,代码压缩再经过gzip,大小 24.60KB ,通常如果我们只用到基本的节点操作,使用 node-base 模块就可以,大小 19.08KB,加上一个 28KB 的yui.min.js,还是比jquery小的,而且利用nginx下concat或者minify,yui-loader就可以在线合并这些资源文件,请求数的问题也迎刃而解了,为了照顾从jquery转向yui的用户,yui从3.2开始还提供了一个simpleyui模块,包含了大量常用模块。

就我现在的感受,构建一个webapp,yui一站式解决,如果用jquery,还要去找backbone之类的mvc框架,然后还要再找个loader或者离线打包,真的麻烦啊,我以前就这么搞的(话说原来想用seajs的,年初还是什么时候,发现seajs.com无法访问了,还以为玉伯你不搞了呢,然后用了requirejs+r.js的方案),如果做一个简单的webpage,用jquery确是挺方便,但是用simpleyui也很方便啊,文件也很小,才 50KB,如果可以一站式解决,我也可以将更多的注意力放在产品实现的细节上,何乐而不为呢?

jQuery 在我心中,是一尊女神。她温柔、细腻,她火辣、傲娇,一定会有人骂她,但真了解她的,会爱上她。

对于使用jQuery的开发者来说,相信大家大部分都是做业务开发的,项目排期,需求的经常变更,使用jQuery在一定程序上还是大大提高了我们的开发效率!

coswind commented Feb 27, 2013

"这段代码很酷,看见了递归没?还有传说中的函数式编程!"...这就是吐槽啊。。哈哈,那个for循环也必须要吐槽下。。

realdah commented Feb 27, 2013

顶。。说的挺好的。

majorye commented Feb 28, 2013

专注+实践

mark,慢慢消化~

mhyailz commented Mar 7, 2013

学习,,,~

给力!!句句到肉!

shiyun commented Mar 19, 2013

jquery虽好,但只会jquery,不会原生js是不被大公司认可的!

welpher commented Mar 19, 2013

项目之痛啊

Owner

lifesinger commented Mar 19, 2013

@shiyun 你说的那些大公司都不是真正的大公司

@lifesinger 玉伯大牛为什么这么说呢?

Owner

lifesinger commented Mar 19, 2013

@steeeeps 会原生js不代表什么,会jq才叫牛。

@lifesinger 额,大牛这句话,我不是很赞同,jq也是从原生js开始一步步构建成的,而且在学习jq的时候,也大都鼓励有精力和时间去研究jq的源码,也是在提倡去学习jq丰富的接口和功能下,是怎么使用原生js来实现的。我觉得那您的话应该这样说,会jq是牛,会jq还会原生js的才叫真牛!哈哈

玉伯这句话又要引起争论了。

在 2013-3-19,下午4:28,lifesinger notifications@github.com 写道:

@steeeeps 会原生js不代表什么,会jq才叫牛。


Reply to this email directly or view it on GitHub.

@steeeeps 研究 jq 的源码的目的不是为了看功能怎么实现,而是学习怎么写出结构更加优美的代码。能用原生 js 写出 jq 的效果的人很多,但是同时能把结构写得优美的人很少。

@CantonBolo 是的,jq的结构以及api的设计是非常优美的,这点我非常认同,我说的研究 jq 的源码的意思主要是说通过jq来加强对原生js代码的学习。如果 @lifesinger 说的会jq才叫牛,指的是真正读懂jq 优美的结构设计,那我觉得他说的非常有道理

@steeeeps 个人认为 jq 并不适合用来学习原生 js 代码,反而一些小类库更加容易看懂。

@CantonBolo 好的,谢谢你的建议

jQuery的API还是有些坑的,像属性存取这类比如html(),text(),attr()等,
如果设置的时候是传入一个变量,而且由于某种原因,这个变量的值是undefined……那种,链就断了,一个Error被抛了出来……

比如

var title = getTitle();
$("#title").text(title).css(titleCssObj).show();

如果getTitle返回了undefined
实际$("#title).text(title)等同于$("#title").text(),返回一个string,后面的链自然就断了

所以比较好一点的写法是

$("#title").text(title || "").css(titleCssObj).show();

更好一点的是把text的参数改为

title || $("#title").text() || ""

或者就简单的把text调用放在最后……

说偏了……其实我想说的是,如果把这个分成getText()和setText(),会不会更方便一些呢……只是每次要多写3个字母。
刚才做了个实验

var f = function() { console.log(arguments); }
f(undefined)

其实arguements并不是空的,所以jQuery完全可以用arguments.length来判断哦

liyao commented May 22, 2013

John大叔创立jQuery的时候或许没有想到日后会这么火,jQuery降低了js的学习门槛,让没有很多基础的新手接受了js的这个概念。从使用jQuery入门,进而学习js的人我认识的就有不少。有人爱jQuery,有人黑jQuery,个人觉得黑它更多的是在黑对它的滥用吧,就像很多人黑js,知道jQuery是用来做什么的,擅长做什么,为什么这么用,才能更好的用它写出优雅的代码。

学习了,感觉目前自身技术正遇到一些瓶颈,看了LZ站在这种高度写的文章的确很受启发,知其然并志气所以然,触类旁通举一反三,收获了很多,谢谢~

fengdi commented May 24, 2013

节约程序员时间的库(框架)就是好库(框架), jQuery是空姐,屌丝们开撸

element.className.match(/(?:^|\s)continue(?:\s|$)/)
我是你湿兄的话看到这段正则根本不会给你加薪、升职。。。
element.className.match(/\bcontinue\b/)

这两天登Github总是页面显示不完整,终于好了,继续学习……

这两篇文章一起看是种享受,同一个话题,跟着Winter学辩论,跟着玉伯学哲学,一边是在谈笑间理清了思维死角,一边是看透过纷扰表象直指本质。

说说自己的理解,有些粗浅,如有走偏,还请各位朋友指教。
1、解决问题
目前理解是:jQuery的意义在于简化DOM操作,是专注于DOM操作的类库,优点是让前端程序员可以高效方便地操作DOM(强大的API)和跨浏览器(兼容性),缺点是到移动场景下,这两点都有局限。
玉伯这话记下了,慢慢体会:“在类库界,解决了 What,解决了定位问题后,基本上已经决定了生死存亡。” 

2、命名
前端的代码,多多少少是开放或开源的,天生比其它语言的命名更容易引来争议,想起了前阵子的Azer Koçulu删除了自己的所有npm库,引发点不就是kik命名吗?

3、接口设计
重载越多,学习成本越高。在前端技术发展很快的前提下,是不是重载越少、库用起来越简单、就越好?

4、耦合
记得在玉伯另一篇文章里也谈到粒度,“适度灵活、适度重复”,我想是这个适度的把握得靠丰富项目经历来培养,正如我们猎头,推荐的精准度也是随着操作case数的增加而增加。

@ringcrl ringcrl referenced this issue in firekylin/firekylin Nov 24, 2017

Open

发表文章出现未知错误 #447

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment