为什么说jQuery老了?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_41694291/article/details/99689796

很多人都说jQuery老了,我本人也承认这一点。

回想十几年前,jQuery的出现曾经席卷前端领域,让混乱的前端开发归为统一,同时广大前端开发者也第一次拥有了一件真正趁手的“兵器”。十几年过去了,这件“兵器”慢慢地钝了,在新涌现的“轻武器”面前显得非常笨重,于是前端开发者们纷纷“拥抱新技术”,有些人甚至对jQuery这个“老古董”嗤之以鼻。

不过别忘了,即使是“小学课本上的那些文章”,仍然是中国文学中最优秀的作品之一,对于我们这些“长大了的孩子”来说,仍然有着不可企及的高度。

jQuery为什么存在?

从第一款浏览器NCSAMosaic诞生开始,实际意义的前端开发就已经存在了。那时人们的需求相当简单 - 在浏览器里看各个资源网站的文章。要是哪个网站能配上几张好看的图片,那一定更能俘获用户的“芳心”。于是有一部分人就开始专注于网页排版,做让用户看起来更舒服的网页,这部分人就是“前端开发”的先锋队。

当然了,即使是最伟大的画家,没有合适的画笔和颜料也难以成就巨作。刚刚诞生的浏览器虽然在技术上已经让人们大开眼界,但是从一个前端“艺术家”的角度来看,这完全是一个蹩脚的作品。事实上,早期浏览器的功能性远远超过它的艺术性(这就像是一块砖,无论被用在多么伟大的建筑上,也不会有人对着一块砖咏叹)。浏览器厂商当然深知这一点,于是近乎疯狂地为浏览器注入新的功能,让它能成为前端“画家”更趁手的“画笔”。

但是标准化往往发生在技术成形之后。所以在早期,浏览器厂商的研发是完全“自由”的。对于两大浏览器巨头Netscape和微软来说,这是建立“霸权”最好的时代!只要一方向浏览器添加了一项新功能,另外一家马上就会效仿。但是,这并不意味着两者会采用同样的方式来实现(比如现在你想要过河,那么坐船或者过桥都可以,而这取决于浏览器为你提供了“船”还是“桥”)。久而久之,两个浏览器中充斥着大量对于相同功能的不同实现,浏览器厂商会为开发者提供一套自己的编程接口,只有使用这套接口,代码才能在这个浏览器上平稳运行(当然也不一定,浏览器总是有bug存在)。

这就苦了前端开发者了,他们写的代码既要保证“坐船的时候不晕船”,又要保证“过桥的时候不恐高”。网页开发者的代码需要经受诸多浏览器的考验,确保在主流浏览器上都能正常运行。于是那时的代码经常是“面向判断”开发的,如果在IE中就怎么怎么样,如果在Navigator中就怎么怎么样,为此还催生了一整套的浏览器兼容手段。前端开发者需要专门学习如何才能让自己的代码在各大浏览器中平稳运行,一时间,兼容各大浏览器的能力成了一个前端开发者最引以为傲的资本。

经历了若干年的痛苦之后,有一个浏览器兼容专家John Resig站出来发话了。凭什么浏览器厂商我行我素,却要前端开发者来背锅?于是他为前端开发者写了一个强大的兼容工具库 - jQuery。作为前端开发者,现在你不用考虑选择哪种方式过河了,只要把眼睛一闭,John Resig就能带你到对面。

当然了,jQuery的功能可远远不止浏览器兼容这么简单。开发者只要使用jQuery,不仅可以免去浏览器兼容的痛苦,还可以得到一大批封装好的工具。想做个动画效果吗?自己写一个要好几十行代码,用jQuery一行就搞定。想发个http请求吗?自己写不仅要进行浏览器兼容,还要写一大堆的回调,用jQuery传几个参数就搞定。想绑定监听事件吗?对不起,原生DOM对象只能绑一个,绑多了就覆盖,用jQuery的话,John Resig帮你存起来,等到需要的时候挨个帮你触发。

说了这么多,其实jQuery所做的工作并没有什么神秘的,就是把开发者需要用大量代码去实现的有用功能封装成工具,提供给开发者使用(打个比方,如果说以前盖房子需要自己烧砖,那么现在John Resig已经帮你烧好了,拿来就可以用,而且保证是最好的砖)。

如果说jQuery是个工具库,这其实没什么问题。但是jQuery对前端的真正意义并不是作为一个工具库,而是作为一个“增强”库。它大大增强了JavaScript这门语言的能力,也让大家看到了这门语言更多的可能性。JavaScript也是吸收了jQuery库中大量的优秀特性和设计原理(典型的比如document.querySelector,就是在jQuery的核心选择器Sizzle上发展而来的),才有了今天这般欣欣向荣的景象。可以说,jQuery就是JavaScript的“小学课本”。

扫描二维码关注公众号,回复: 7637993 查看本文章

jQuery为什么优秀,以及jQuery为什么不优秀了?

jQuery为什么优秀?因为它是JavaScript最好的“学步车”。它通过封装实现细节,规范了JavaScript和浏览器的大多数怪异行为,所以对于深陷浏览器兼容泥潭的前端开发者来说,它是最好的选择。那为什么说jQuery不优秀了?这其实不是jQuery本身的原因,而是因为JavaScript“长大了”。

在互联网发展早期,人们对网站的功能要求不高,通常单个网页的代码量也就几百到几千行,开发者可以将这点代码轻松“玩弄于股掌之中”。有了jQuery之后,即使是稍微复杂一点的网站,代码写起来也是干净利索。jQuery带给开发者的使用体验就如同iPhone1带给世界的惊喜一样,人们不仅会赞叹它超前的技术创新,更折服于它无与伦比的艺术审美。甚至是后来互联网工作组在更新迭代JavaScript的时候,都会大量吸收jQuery的优秀特性,以及来自jQuery社区很多好的想法。jQuery可以说是第一个把JavaScript扶上正轨的前端库。

但是随着互联网的发展,人们对浏览器的使用越来越频繁,越来越多功能庞杂的网站被开发出来,以满足不同用户的需要。这些网站动辄上万行代码,业务关系非常复杂。而使用jQuery进行网站开发,需要网站开发者精心控制用户的每一个操作。举个例子,当用户点击了页面上的某一个按钮,网站开发者需要考虑到跟这个点击事件相关的所有后续影响(这里所说的影响通常指DOM操作,即更新页面上某一区域的内容),妥善地处理这些影响。虽然说有了jQuery之后,很多后续影响只需要一行代码就可以解决,但是如果是在上万行代码的网页中进行操作,问题往往就不那么简单了。

最初那个几百行代码就可以做个线上网页的时代一去不复还了。在一个功能复杂的网页中思考当前的用户事件会造成哪些影响是很耗费心力的,许多前端开发者都会感觉力不从心。更糟糕的是,一旦开发者感到力不从心,他们就更难找到更新页面的最优方法(比如现在需要更新一个表格的若干行数据,为了节省精力,他们可能会选择刷新整个表格)。

jQuery最终还是败给了互联网的发展。

新的框架为什么能打败jQuery?

这里指的新框架,就是目前前端的三大主流框架React/Vue/Angular。如果说jQuery为开发者提供了解决问题的工具,那么这些框架是为开发者提供了解决问题的新思路。

使用jQuery时,开发者需要精心掌控全局,用户与网页的每一次交互,开发者都为它定义好了相关的处理流程,整个网站将按照开发者定义的流程平稳运行。jQuery的出现让流程定义变得更简单,更通用,也更强大。但是无论流程的定义变得多么简单,当需要定义的流程变得足够多的时候,它也就不再简单了。

而新的框架尝试通过视图与业务的分离解决这个问题,它们的中心思想也从定义流程变成了定义规则。假如现在页面上有一个表格,那么在JavaScript中就会有一个与它对应的数据对象。当这个数据对象的值发生了变化时,页面上的表格就需要跟着发生变化,对数据对象的操作被归为业务逻辑,而页面上的表格被归为视图。传统的jQuery开发需要我们根据数据的变化定义表格的更新流程(比如先删除某行,然后更新某行),这样往往极其繁琐。我们希望当数据变化时,框架应该“知道”怎么去更新这个表格,那么我们以后只专注于操作数据就可以了。这就是MVVM的设计原则了。那么框架怎么“知道”如何更新表格呢?不同的框架有自己的解决方案。

React的解决方案

React使用虚拟DOM树来实现自动更新视图。使用React进行开发时,通常会用到React推荐的JSX语法,这是一种类HTML的JavaScript语法,React可以从这种代码中构建一棵虚拟DOM树。开发者通过在JSX模板中绑定变量来定义数据如何显示在视图上,比如:

const element = (
    <h1>
        Hello, {uasename}!
    </h1>
);

username是业务系统中的一个变量,它现在被绑定到了视图中。现在React就知道,当username变化时,element组件是需要更新的。那么如何更新呢?React借助虚拟DOM树的diff算法来进行比对。下面是一棵真实的DOM树(图片来自网络)
在这里插入图片描述
所谓虚拟DOM,就是将上面这个DOM结构用对应的JavaScript对象来替换(虚拟DOM只会描述body下面的节点,因为只有body下面的节点才需要渲染),每个对象只保留对DOM节点尽量少但足够完备的描述。React会把这样一个描述存储在内存中(React并不会一次描述整棵DOM树,而是将整个的虚拟DOM拆分成很多分支,分别维护,每个分支就是一个组件)。假如某个数据变化了,React会生成新的虚拟DOM树,通过diff算法,将新旧两棵虚拟DOM树进行比较,判断哪一部分需要更新,然后以尽量小的代价去更新真正的DOM树。这个比对和更新的过程完全不需要开发者参与。对开发者而言,一旦将数据和视图绑定了,那么当数据变化后,视图也跟着更新了。

Vue的解决方案

Vue选择的是响应式系统 + 虚拟DOM来解决这个问题。从理论上来说,Vue对虚拟DOM没有任何依赖,Vue的自动更新是建立在自身的响应式系统上的。最初版本的Vue没有引入虚拟DOM,以响应式系统完成了自动更新视图的功能,性能甚至比现在两者结合的方式更高。但是构建响应式系统是以内存为代价的,一个完整的响应式系统中包含了大量的Observer和Watcher,这在浏览器受限的内存条件下是不允许的,所以Vue的作者引入了虚拟DOM,来减少Watcher的数量(同时牺牲了一定的性能)。

下面的代码可以很好地说明Vue的响应式系统原理(引自Vue2.6.10 src/core/observer/index.js):

//为obj的key属性定义get/set,get用于收集依赖,set用于触发更新
Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()		//收集依赖
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      // #7981: for accessor properties without setter
      if (getter && !setter) return
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()  //触发更新,数据变化时通知Watcher
    }
  })

响应式的核心就在于上面的两条语句:
get方法中的:dep.depend() //收集依赖
和set中的:dep.notify() //数据变化时通知Watcher
它使用Object.defineProperty来定义对象属性的get/set,在get中收集依赖,注册监听器;在set中通知监听器,自动更新视图。这样,当一个数据发生了变化时,就会触发set方法,Vue就自动调用更新视图的方法,更新页面。

Vue对数据的监控粒度很细,因此更新效率很高,但是如此细粒度的监控会产生大量的Watcher,这也导致框架在运行时非常吃内存。于是作者选择了使用虚拟DOM来降低内存使用,当数据发生变化时,不是直接更新节点,而是通知对应的组件,通过diff算法去比对,决定最终更新哪些节点。

Angular使用脏检查来解决这个问题,由于接触甚少,这里不再展开描述。

通过上面的介绍可以看出,使用了新的框架之后,开发者不再需要严格定义每一个更新流程,只需要在框架中定义哪些数据和哪些视图绑定(即view-model,这是定义规则的过程)。这样开发者只需要把关注点聚焦在业务逻辑上,考虑如何操作数据。当数据更新之后,框架就会通过自己的解决方案更新视图,因此开发效率大大提升。在这种新的开发模式下,jQuery代码更加显得冗长和复杂,在前端领域败给了这些后起之秀。

jQuery还有用吗?

显然,jQuery在前端领域已经不再有往日的影响力了,而且可以预见的是,它的市场份额一定会越来越少。但如果是为了学习JavaScript,那么我认为,jQuery的价值依然存在,它仍然是一个非常优秀的JavaScript库(毕竟这十几年来,全世界的前端开发者都证明了它的优秀,此外jQuery封装代码的方式跟设计思想包括某些核心模块(如Sizzle选择器)直到今天也不过时)。所以如果你认为自己和我一样,在前端领域还是个“孩子”,那么我推荐你阅读jQuery的源码,它将是一个很好的“学步”工具。

总结

本文并不是一篇严谨的学术文章,只是我本人对jQuery的一些浅显认知,希望对从未接触过jQuery或者使用很少的前端开发者带来一些启发。

最后回到本文的核心问题,为什么说jQuery老了?因为JavaScript“长大了”,前端领域也慢慢成熟了,jQuery作为一个“学步车”,必然要退出历史舞台。

历史总是向前发展的,jQuery有老去的一天,现在主流的三大框架也会有那么一天。虽然说业务与视图分离是很好的设计思想,但是目前自动更新DOM的效率却并没有想象中那么高(个人意见)。也许有一天,前端框架中也会加入某些人工智能算法,它们通过“观察”用户操作,学习如何以最高效的手段更新DOM,同时将内存和时间代价都降到最低,我觉得,这样前端才算真正的成熟了(也可能有一天,人们觉得现在的浏览器模型不够好了,又设计出了新的浏览器模型,前端又会是怎样的一片场景?我很想知道,也很想参与)。

所以准备好迎接挑战吧!

猜你喜欢

转载自blog.csdn.net/qq_41694291/article/details/99689796