JavaScript、jQuery、AJAX、JSON 这四个之间的关系?

时间:2022-08-23 08:01:44

JavaScript、jQuery、AJAX、JSON 这四个之间的关系?

http://www.zhihu.com/question/31305968

作者:艾拉斯
链接:http://www.zhihu.com/question/31305968/answer/116439739
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

1. JavaScript

JavaScript(简称js)是一种主要运行于浏览器中的弱类型的动态脚本语言,可以用来实现网页上的一些高级功能,如数据验证处理、页面动态效果、定时任务、与用户交互、发送/接收服务器端数据等等。

动态语言指的是程序运行时可以改变结构,主要体现在:
① js中的变量在声明的时候不需要指定类型,其实际类型由程序运行中的赋值决定,在运行过程中变量的类型也可以改变。注:这一点是动态语言的特征,并不是弱类型语言的特征,之前的回答有误。
② 函数可变。js允许在运行过程中使用eval动态执行字符串里的命令,也可以通过new Function等方式由字符串动态构造函数,函数可以被创建、修改、删除,可以从已有函数构造出新函数,等等。
③ 对象的成员可变,可以动态添加、删除成员属性或成员方法。

弱类型指的是js中的变量在参与运算的时候可以根据实际需要动态转换类型。与之相对应的是强类型语言——变量一般不允许自动转换类型(某些强类型语言的字符串连接操作除外),如果参与运算、调用时不符合要求的类型,则会在编译阶段报错。

js是1995年由Netscape公司的Brendan Eich为自家的浏览器Netscape Navigator开发的,当时意图是用于网页上的表单验证,即验证表单的各个输入项是否符合预定规则,在验证通过后才向服务器提交表单内容,减少页面与服务器端不必要的频繁交互。

js的最初版本只用了10天就开发完成,当然不是完全从无到有,而是借鉴了其他一些语言的特性来开发。如此仓促开发,js自然有一些先天不足,但同时也具备了基于弱类型动态语言的方便灵活、对象原型继承、函数是一种特殊的对象等优秀特性,于是越来越得到广泛应用,而语言自身也在标准化组织的推动下不断发展进步。

在浏览器发展的早期,Microsoft仿造JavaScript推出了相似的脚本语言JScript,在IE浏览器中使用,Microsoft同时推出的还有VBScript。后来为了解决不同浏览器中脚本语言不兼容的问题,在ECMA(欧洲计算机制造商协会)成立了标准化小组,由各厂商参与,共同制定JavaScript的语言规范,规范化的这门语言被命名为ECMAScript。

js也可以在浏览器之外的其他场合使用,如服务器端的Node.js、java的Rhino、*面浏览器PhantomJS等。

2. jQuery

jQuery是js的一个工具库,由John Resig在2006年发布。
j代表JavaScript,query是“查询”的意思。也就是说,这个库的意图是基于JavaScript的查询。
查询的目标是什么?答案是DOM(文档对象模型)结构中的Node(节点)。一个网页就是一个html文档,而网页上的所有内容都是节点,包括文档节点、元素节点、文本节点、注释节点、属性节点等等。而jQuery的查询最主要针对的是元素节点,如段落(p)、锚点(a)、表格(table)等,只有少数方法可以处理文本节点与注释节点。同时jQuery还可以用attr方法方便地对元素节点的属性进行读取/设置。

在jQuery出现之前,在js程序中获取元素节点比较麻烦,例如获取id为elem1的节点:
document.getElementById('elem1')
或者是获取页面上的所有checkbox元素,首先需要获取input类型的元素:
document.getElementsByTagName('input')
然后对获得的元素列表进行for循环处理,逐个判断其类型是否为checkbox。
如果有更多元化的查询要求,则对应的js代码也会相当复杂。虽然有一些库可以解决这方面的需求,但强大程度、易用性等方面都不太理想。

John Resig发现了一个盲点——css样式应用到页面上的元素时,是有一套规则的,即css选择器,浏览器可以通过css选择器找到匹配的元素并将指定的样式应用到这些元素上。也就是说,通过css选择器可以有效地进行元素查找定位,但它最初只被用于样式领域。于是,John Resig根据css选择器编写了jQuery选择器,并对选择器的规则进行了扩充,从而让元素查找变得非常方便。例如,上面2个例子用jQuery可以写为:
$('#elem1')

$(":checkbox")
同时,jQuery还有一个核心思想——链式操作,例如:
$('div.con')
.height(100)
.show();
这样的连续调用可以让代码书写更加简洁,也就是jQuery自己的口号:write less, do more。

此外,jQuery还提供了浏览器兼容、样式读写、事件绑定与执行、动画等特性,后来又加入了ajax、promise等,再加上方便的插件编写机制,对整个js的生态圈产生了重大的影响,可以说是js历史上影响力最大的一个库。其中选择器引擎后来被单独剥离出来成为sizzle,供其他的js库调用。这部分的工作还影响了官方,在jQuery成功之后,浏览器才有了querySelector与querySelectorAll方法。时至今日,虽然有了querySelector与querySelectorAll,但jQuery的选择器仍然有少部分特性是前2者所无法替代的。

3. ajax

ajax全称Asynchronous JavaScript and XML(异步的JavaScript与XML),是网页无需刷新页面、使用js与服务器进行交互的一种技术。

有时候会有这样一种需求:只希望更改页面上的一个区域。然而在从前的技术框架内只能刷新整个页面,带来的后果是:①需要重新传输整个页面,服务器端与客户端的流量消耗都会比较大;②如果是动态页,服务器端需要重新生成整个页面,即使是那些客户原本不想要刷新的区域,增大了服务器的负担。

Google的Jesse James Garrett在2005年初发表了一篇文章,提供了解决这种需求的技术方案,也就是ajax。实际上这是一种实践先行的技术,该方案的技术依赖之一XMLHTTP在1998年就已经被Microsoft开发出来了,而Google在若干年后使用这项技术开发Google Maps等产品之后,才发表了相应的文章并对其进行了命名。

ajax的基本流程可以概括为:页面上js脚本实例化一个XMLHttpRequest对象,设置好服务器端的url、必要的查询参数、回调函数之后,向服务器发出请求,服务器在处理请求之后将处理结果返回给页面,触发事先绑定的回调函数。这样,页面脚本如果想要改变一个区域的内容,只需要通过ajax向服务器获取与该区域有关的少量数据,在回调函数中将该区域的内容替换掉即可,不需要刷新整个页面。

XMLHttpRequest在发送请求的时候,有两种方式:同步与异步。同步方式是请求发出后,一直到收到服务器返回的数据为止,浏览器进程被阻塞,页面上什么事也做不了。而异步方式则不会阻塞浏览器进程,在服务端返回数据并触发回调函数之前,用户依然可以在该页面上进行其他操作。ajax的核心是异步方式,而同步方式只有在极其特殊的情况下才会被用到。

XMLHttpRequest在早期IE浏览器里是使用ActiveX来实现的,并不是浏览器自身的对象。后来其他各家浏览器也都实现了XMLHttpRequest对象,而高版本IE也把XMLHttpRequest改为了浏览器的内建对象。

4. JSON

JSON全称JavaScript Object Notation(js对象标记法),由Douglas Crockford在2002年发现并制定了标准。从名称上就可以看出来,JSON是基于JavaScript的,是JavaScript的一个子集。JSON是用JavaScript语法来表示数据的一种轻量级语言。

虽然Douglas在2002年就注册了,并且为各种语言编写了解析与构造JSON数据的库,但在最开始的几年JSON一直没有得到足够的重视。情况一直延续到ajax的出现。

从ajax的命名中我们就可以看到,数据交换是通过XML格式进行的。在ajax刚出现的时候,绝大多数应用都是采用XML格式,也有少数使用纯文本的。但是XML格式有一个缺点,就是文档构造复杂,需要传输比较多的字节数。在这种情况下,JSON的轻便性逐渐得到重视,后来替代XML成为ajax最主要的数据传输格式。可以举个简单的例子感受一下二者的区别:

<?xml version="1.0" encoding="utf-8"?>
<root>
<article>
<title>Article Title1</title>
<content>content1</content>
</article>
<article>
<title>Article Title2</title>
<content>content2</content>
</article>
</root>

{
"article" : [
{
"title": "Article Title1",
"content": "content1"
},
{
"title": "Article Title2",
"content": "content2"
}
]
}

XML规范实际上是比较复杂的,单纯作为数据传输来说它太重了。在ajax领域中JSON取代XML的过程,是一个很好的“用脚投票”的范例。

而JSON的影响力在此后还继续扩大,有些软件将其作为配置文件的格式,有些编程语言也吸纳了JSON的优点。例如c#,在高版本里可以这样写:

Dictionary<int, string> dict = new Dictionary<int, string>{
{1, "a"},
{2, "b"}
};

但是如果c# 2.0这样写,可是会报错的。在2.0里只能写成下面这种形式:
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "a");
dict.Add(2, "b");
等价于
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "a";
dict[2] = "b";

比较一下两种写法的区别,不仅有便捷性的差距,而且前一种写法可以在声明变量的同时为变量赋值,后一种写法则不行,这会影响到类属性的初始化操作:在c# 2.0中,只能把针对Dictionary之类复杂对象的初始化代码写在函数里,而不能直接写在类属性的声明处。

感觉上是c#受了JSON(或者说js)的影响。但此处是我个人的感觉,如有错误请指出。

回到js自身,对于对象构造有两种方法:基于对象的完整写法,字面量表示法。前者如:

var obj = new Object();
obj.title = "title1";
obj.content = "content1";
而与之对应的字面量表示法则写为:
var obj = {
title: "title1",
content: "content1"
};

可以明显看出字面量表示法要简洁得多。而JSON基本就是字面量表示法的一个子集,除了强制要求键与字符串类型的值必须用双引号包起之外,它剔除了undefined、function等类型,也不包括浏览器内置对象类型(如Date、RegExp等),是基于文本的、比较纯粹的数据表示方法。所以说,Douglas是“发现”了JSON,而不是“发明”。标准的JSON不包含注释,但后来因为实际需求而出现了能够处理注释的JSON库。

5. Node.js

Node.js是Ryan Dahl在2009年发布的、主要用于服务器端的Javascript运行环境,也可以用于个人电脑。
Ryan Dahl此前一直在寻找一种事件驱动型的、异步的服务器端框架,实际上,js并不是他的首选。他是在尝试了几种语言之后,才发现js的函数回调与单线程特性正好契合他的要求,于是Node.js应运而生。
js的异步回调在ajax的部分已经提过:在调用异步方法的时候,可以将后续的处理函数作为参数传入,在调用相应的异步接口之后,程序会将线程的控制权让出,允许其他代码执行;在接口返回处理结果后,再执行后续处理函数(即回调函数)。实际上,因为js是单线程语言,回调函数并不是立刻被执行的,而是会被送入任务队列,在线程空闲、并且队列前方没有其他任务的情况下,才会被执行。

用户在向服务器提交请求的时候,如果处理比较费时,传统的服务器端框架会导致处理线程被阻塞。而js的特性使得异步任务在执行的时候让出线程的控制权,在处理完成后再进行正确的回调,从而能够获得比较好的高并发处理能力。
js本身是一门严格的单线程语言,而Node.js为了充分发挥服务器的处理能力,在运行环境级别上增加了对于多线程的支持(child process)。但Node.js的多线程与常规的多线程有很大区别——常规语言的多线程允许多个线程共享数据,或者调用其他线程暴露出来的公开方法,而Node.js的多线程只能用消息机制进行通讯。这样,Node.js就规避了常规多线程的数据同步、线程锁(线程同步/互斥)等复杂问题,规避了一些潜在风险。

Node.js使用的V8引擎实际上就是Google的Chrome浏览器使用的Javascript引擎(因为V8引擎是开源的),并进行了模块扩展。例如遵循CommonJS标准的模块定义,适合服务器需求的多线程、集群、HTTP/HTTPS,文件系统,等等。Node.js中的很多方法都同时提供了异步版本与同步版本,从函数的命名上可以简单区分。
得益于其模块特性,Node.js的模块扩展变得相当方便,用于Node.js包管理的npm得到了广泛的使用,但也曾经引起“是否过度使用依赖包”的争论。

Node.js不仅可用于服务器端,因为其安装完成之后可以用命令行方式方便地调用,因此在个人电脑中也逐渐得到广泛应用。例如为代码编辑器提供插件、用于桌面的Node.js App等。另外还有一个重要的应用领域就是前端自动化,包括代码的预编译/转换(如使用Babel将ECMAScript 6的代码转换为低版本的es代码,将sass/less的样式表文件编译为传统的css文件)、语法检查、代码文件或图像文件的合并、代码的混淆/压缩、自动分发、自动测试等,还可以监视开发文件夹,在内容改变时自动执行上述操作,并自动刷新浏览器页面。这样使得前端领域的开发方式得到了大大进化。

js虽然因为有着一些先天不足而被人诟病,但这些年来却越发展越壮大。这不仅仅是因为依托于浏览器这个宿主环境,更是因为其自身具备的一些优秀特性,Node.js的出现与发展就是一个很好的例证。

总结

ajax与Node.js都使用了js的异步回调特性。
jQuery的出现解决了那个各方面标准尚未统一的混乱时代的许多问题,让js的应用更加广泛,并为未来某些标准的制定指明了方向。
JSON从js中脱胎而出,作为一种简洁、扩展性好的轻量级数据表示方法,在很多领域得到了广泛使用。
Node.js在服务器端与开发流程中都越来越得到重视。
由于Node.js不包含BOM与DOM,因此jQuery不能直接在Node.js上使用,但可以借助jsdom、cheerio之类的库,在构造出虚拟的dom结构后再使用。查看github上的jQuery开发包,可以看到它使用了Node.js上的grunt来进行自动化构建、测试的工作。
以上几项技术的共同进步,配合浏览器的进步,此外还有硬件条件的发展,让复杂的页面应用越来越多,许多以前在服务器端进行的工作可以转到客户的浏览器中进行,顺应了分布式处理的潮流。