jq和es6

一、初识jQuery.js

jQuery.js是一款优秀的JS类库,其本质就是在一个立即执行的匿名函数中的闭包,jQuery=js+Query(查询),从命名可以看出jQuery.js最主要的用途是用来做查询,在jQuery.js官方Logo下方还有一个副标题(write less, do more),体现了jQuery.js除了查询以外,还可以实现强大选择器(即方便快速查找DOM元素,jQuery.js允许开发者使用CSS1-CSS3几乎所有的选择器,以及jQuery.js独创的选择器),链式调用(即可以通过“.”不断的调用jQuery.js中的各种方法),隐式遍历/迭代(即一次操作多个DOM元素),读写合一(即读数据和写数据使用同一个jQuery方法),事件处理DOM操作(即C增U改D删),样式操作动画丰富的插件支持Ajax变得更加简单浏览器兼容(即解决前端开发者痛点),1.x版本兼容ie678,但相对其它版本文件较大,官方只做BUG维护,功能不再新增,最终版本是1.12.4(2016年5月20日),2.x版本不兼容ie678,相对1.x文件较小,官方只做BUG维护,功能不再新增,最终版本是2.2.4(2016年5月20日),3.x版本不兼容ie678,只支持最新的web浏览器,不支持很多老的jQuery.js插件,相对1.x文件较小,而且3.x提供不包含Ajax/动画API的版本,我们通过查看百度、腾讯、和京东的网页源代码,发现使用的都是1.x版本,所以我们学习1.x版本就可以了,开发版的意思是所有的源代码没有经过压缩,所以体积更大(200-300KB),生产版的意思是所有的源代码经过了压缩,所以体积更小(30-40KB),为了初学者更好的理解jQuery.js,当开发时,我们使用开发版,当项目上线时,为了提升访问速度,我们再换成生产版即可,首先上官网“jquery.com”下载jQuery.js类库,然后在我们自己的.html文件引入所下载的jQuery.js类库,最后编写jQuery代码即可,原生JS入口函数的固定写法是“window.onload = function () {可执行的代码;};”,当写了多个原生JS的入口函数时,先编写的会被后编写的所覆盖,由于原生JS的入口函数会等到此页面上的img加载完毕再执行,所以当此页面上的一个<img>没有设置宽高时,利用原生JS的入口函数可以获取到此<img>的宽高,jQuery.js入口函数的固定写法是“$ (document).ready (function () {可执行的代码;} );”/“jQuery (document).ready (function () {可执行的代码;} );”/“$ (function () {可执行的代码;} );(//推荐)”/“jQuery (function () {可执行的代码;} );”,当写了多个jQuery.js的入口函数时,先编写的不会被后编写的所覆盖,由于jQuery.js的入口函数不会等到此页面上的img加载完毕再执行,所以当此页面上的一个<img>没有设置宽高时,利用jQuery.js的入口函数无法获取到此<img>的宽高,当引入了多个类库/框架,并且其它类库/框架也有$符号时,$符号的使用势必就会有冲突,所以我们可以释放jQuery代码中$符号的使用权,在编写其它jQuery代码之前写上一句“jQuery.noConflict ();”即可,释放之后就不能再使用$符号了,可以改为使用jQuery,还可以自定义一个符号来代替jQuery,例如“var nj = jQuery.noConflict ();(//从此nj就代替了jQuery的功能)”

二、jQuery.js中的核心函数和工具方法

$就代表jQuery这个类库名,只不过简写为$,“$ ();”就等同于“jQuery ();”,代表调用jQuery.js的核心函数,在调用的时候可以向里边传参,可以传入一个回调函数,即入口函数,格式为“$ (function () {可执行的代码;});”,可以传入一个空字符串/null/undefined/NaN/0/false,返回值是一个空的jQuery集合,可以传入一个基本数据/对象/DOM元素,返回值是一个保存了所传入的基本数据/对象/DOM元素的jQuery集合,例如“$ (oSpan);”,可以传入一个选择器字符串,例如“$ (“.box1”);(//返回值是一个保存了在此页面上所找到的传入选择器字符串所指代的所有DOM元素的jQuery集合)”,可以传入一个HTML代码片段字符串,例如“$ (“<p>我是段落</p>”);(//返回值是一个保存了传入HTML代码片段字符串所指代的新createElement的DOM元素的jQuery集合,当所传入的HTML代码片段存在嵌套关系时,只有一级DOM元素会保存在jQuery集合中)”,可以传入一个真/伪数组,返回值是一个保存了所传入的真/伪数组中所有元素的jQuery集合,含有0、1、2、...一直到(length-1)的属性以及length属性的对象就叫做伪数组(或者叫伪数组对象),jQuery集合其实就是一个伪数组,原生JS中的forEach和map等方法是无法遍历伪数组的,jQuery集合调用它的get方法可以返回此集合中第传入索引个元素(当不传参时,就相当于调用toArray方法,当传入一个负数时,就相当于用此数值与此集合的总长度值相加),jQuery的DOM元素集合调用它的index方法可以返回此集合中的首个DOM元素在其同级别标签中的索引值,jQuery集合调用它的each方法可以遍历此集合,返回值是调用者,在所传入回调函数的作用域中,this指针指代的是所遍历到的元素,“return true;”就相当于“continue;”,“return false;”就相当于“break;”,jQuery类对象调用它的each方法可以遍历参数1真/伪数组/对象,返回值是参数1,在参数2回调函数的作用域中,this指针指代的是所遍历到的元素,“return true;”就相当于“continue;”,“return false;”就相当于“break;”,例如“var arr = [1, 3, 5, 7, 9];  var obj = {0: 1, 1: 3, 2: 5, 3: 7, 4: 9, length: 5};  $.each (obj, function (index, value) {console.log(index, value);} );(//第一个形参index接收到的实参是所遍历到的索引值,第二个形参value接收到的实参是所遍历到的元素,只能接收到这俩参数)”,jQuery类对象调用它的map方法可以遍历参数1真/伪数组,返回值是参数2回调函数的返回值所组成的数组,例如“$.map (obj, function (value, index) {return value + index;});(//返回值是[1, 4, 7, 10, 13])”,jQuery类对象调用它的trim方法可以返回传入字符串被去除两端空格之后的新字符串,例如“var str = “lnj   ”;  $.trim (str);(//返回值是“lnj”)”,jQuery类对象调用它的isWindow方法可以判断所传入的数据是否是window对象,返回值是true/false,jQuery类对象调用它的isArray方法可以判断所传入的数据是否是真数组,返回值是true/false,jQuery类对象调用它的isFunction方法可以判断所传入的数据是否是一个函数,返回值是true/false,jQuery类对象调用它的holdReady方法可以暂停/恢复ready事件,传入true代表暂停,传入false代表恢复,例如“$.holdReady (true);  $ (document).ready (function () {alert (“ready”);} );(//不会有弹窗)”,jQuery集合调用它的toArray方法可以返回此集合被转成的真数组

三、jQuery.js中的选择器以及操作html网页的各种相关方法

jQuery.js中的内容选择器有“:empty”、“:parent”、“:contains()”、和“:has()”,“:empty”的作用是选中没有任何内容(文本/子标签)的冒号前的标签,例如“var $div = $ (“div:empty”);”,“:parent”的作用是选中含有内容(文本/子标签)的冒号前的标签,例如“var $div = $ (“div:parent”);”,“:contains()”的作用是选中包含小括号内文本内容的冒号前的标签,例如“var $div = $ (“div:contains(‘我是div’)”);”,“:has()”的作用是选中包含小括号内子标签的冒号前的标签,例如“var $div = $ (“div:has(‘span’)”);”,一个对象身上所保存的变量就叫做属性,在JS中,HTML标签的HTML属性就叫做属性节点,任何对象都有属性,但是只有DOM元素才有属性节点,在浏览器的开发者工具(F12)中,点击Sources->右侧的Watch->上面的加号,然后输入例如“document.querySelector (“.one”);”,找到相应DOM元素后,展开之后所看到的都是属性,在attributes伪数组中所保存的所有元素都是属性节点,我们可以调用原生JS中的setAttribute和getAttribute方法来操作属性节点,jQuery的DOM元素集合调用它的attr方法可以返回/修改/批量修改此集合中首个/所有DOM元素的传入系统自带/自定义属性节点字符串的取值(在传入跟取值相同的属性节点字符串时,如checked/selected/disabled属性节点,当调用者添加了所传入的属性节点时,返回值是此属性节点字符串,当没添加时,返回值是undefined,不推荐,碰到此种情况建议改用prop方法,其余情况用attr方法即可),返回值是调用者,例如“console.log ($ (“span”).attr (“class”) );(//首个span元素)”,“$ (“span”).attr (“class”, “box”);(//所有span元素,没有就新增)”,“$ (“span”).attr ({class: “a123”, name: “888”});(//所有span元素,没有就批量新增)”,jQuery的DOM元素集合调用它的prop方法可以返回/修改/批量修改此集合中首个/所有DOM元素的传入属性/系统自带属性节点字符串的取值(在传入了跟取值相同的属性节点字符串时,如checked/selected/disabled属性节点,当调用者添加了所传入的属性节点时,返回值是true,当没添加时,返回值是false,官方推荐),返回值是调用者,例如“console.log ($ (“p”).prop (“title”) );(//首个p元素,当传入一个自定义的属性节点字符串时,返回值是undefined)”,“$ (“p”).prop (“demo”, “lnj”);(//所有p元素,没有就新增)”,“$ (“p”).prop ({class: “a123”, name: “888”});(//所有p元素,没有就批量新增)”,jQuery的DOM元素集合调用它的removeProp/removeAttr方法可以删除此集合中所有DOM元素所传入的属性/属性节点字符串,例如“$ (“span”).removeAttr (“class name”);(//有多个就用空格隔开)”,jQuery的DOM元素集合调用它的addClass/removeClass/toggleClass方法可以给此集合中所有DOM元素添加/删除一/多个所传入的类名字符串/切换addClass和removeClass的状态,返回值是调用者,当调用者拥有所传入的类名时,addClass方法不会重复去添加,当不传参时,removeClass和toggleClass方法会删除调用者所有的类名,例如“$ (“div”).addClass (“class1 class2”);”,jQuery的DOM元素集合调用它的html/text方法既可以返回此集合中首个/所有DOM元素内部包含/不包含两端空格和HTML标签的内容字符串,也可以将此集合中所有DOM元素中的内容设置为所传入的包含HTML标签/普通(即出现HTML标签时会当成普通的字符串)的字符串(html方法也可以传入一个jQuery的DOM元素集合/DOM元素),例如“$ (“div”).html ($ (“p”) );(//会将此页面上的p元素剪切,并设置为div元素中的内容)”,jQuery的input输入框元素集合调用它的val方法可以返回/设置此集合中首个/所有单行文本输入框中所输入的内容字符串,返回值是调用者,jQuery的DOM元素集合调用它的prepend/append方法可以在此集合中所有DOM元素内部的最前/后面添加所传入的HTML代码片段字符串/jQuery的DOM元素集合/DOM元素/文本内容,返回值是调用者,jQuery的DOM元素集合调用它的prependTo/appendTo方法可以将此集合中所有DOM元素添加到传入选择器字符串/jQuery的DOM元素集合/DOM元素内部的最前/后面,返回值是调用者,例如“$ (“<li>新增的li</li>”).appendTo (“ul”);”,jQuery的DOM元素集合调用它的before/after方法可以在此集合中所有DOM元素的前/后面都添加所传入的HTML代码片段字符串/jQuery的DOM元素集合/DOM元素/文本内容,jQuery的DOM元素集合调用它的insertBefore/insertAfter方法可以将此集合中所有DOM元素添加到传入选择器字符串/jQuery的DOM元素集合的前/后面,返回值是调用者,例如“$ (“<div>你好</div>”).insertAfter (“ul”);”,jQuery的DOM元素集合调用它的remove/detach方法可以删除此集合中传入选择器字符串所指代的DOM元素,当不传参时,会删除此集合中的所有DOM元素,返回值是调用者(remove跟detach的不同是,remove还会将被删除DOM元素所绑定的事件以及所附加的数据也一并移除),jQuery的DOM元素集合调用它的empty方法可以删除此集合中所有DOM元素中的所有内容,返回值是调用者,jQuery的DOM元素集合调用它的replaceWith方法可以将此集合中所有DOM元素替换为所传入的HTML代码片段字符串/jQuery的DOM元素集合/DOM元素,例如“$ (“div”).replaceWith ($ (“p”) );(//将此页面上的p元素剪切,并将div元素替换掉)”,jQuery的DOM元素集合调用它的replaceAll方法可以将所传入的选择器字符串所指代的DOM元素替换为此集合中所有的DOM元素,例如“$ (“<h6>我是标题6</h6>”).replaceAll (“h1”);”,jQuery的DOM元素集合调用它的clone方法可以返回深/浅复制的此调用者,传入true/false是深/浅复制,浅复制只会复制此调用者,而深复制除了会复制此调用者,还会复制其所绑定的事件,jQuery的DOM元素集合调用它的css方法可以返回/设置此集合中首个/所有DOM元素传入的行内样式/CSS属性字符串的取值,返回值是调用者,例如“console.log ($ (“div”).css (“backgroundColor”) );(//首个div元素)”,“$ (“div”).css (“width”, “100px”);(//所有div元素,当设置时,设置成的一定是行内样式)”,“$ (“div”).css (“width”, “100px”).css (“height”, “100px”).css (“backgroundColor”, “blue”);(//所有div元素,链式设置,当链式操作大于3步时,建议分开写,否则阅读性较差)”,“$ (“div”).css ({width: “100px”, height: “100px”, backgroundColor: “red”});(//所有div元素,批量设置,当CSS属性名称带有中划线时,要改成驼峰命名)”,jQuery的DOM元素集合调用它的width/height方法可以返回/设置此集合中所有DOM元素width/height属性的取值,例如“$ (“.father”).width ();(//返回值不带单位px)”,“$ (“.father”).width (“500px”);”,jQuery的DOM元素集合调用它的offset方法可以返回/设置此集合中首个DOM元素的左和上边缘与网页可视区域的左和上边缘的距离值对象(包含left和top两个属性),例如“$ (“.son”).offset ().left;(//返回值不带单位px)”,“$ (“.son”).offset ({left: 10});(//传入对象中属性的取值不能带单位px)”,jQuery绝对/固定定位标签伪数组对象调用它的position方法可以返回(但无法设置)此集合中首个DOM元素的左和上边缘与其最近的定位流上级元素的左和上边缘的距离值对象(包含left和top两个属性),例如“$ (“.son”).position ().left;(//返回值不带单位px)”,jQuery的DOM元素/html/body元素集合调用它的scrollLeft/scrollTop方法可以返回/设置此集合中所有DOM元素/此网页横/竖向滚动条滚出的距离值,例如“$ (“.scroll”).scrollTop (300);”,“console.log ($ (“body”).scrollTop () + $ (“html”).scrollTop () );(//为了做兼容性处理,因为IE浏览器支持$ (“body”),非IE浏览器支持$ (“html”))”,“$ (“html, body”).scrollTop (300);(//为了做兼容性处理)”,jQuery集合调用它的eq方法可以返回一个只有此集合中第传入索引个元素的jQuery集合(当不传参时,返回值是一个空的jQuery集合,当传入负数时,就相当于用此数值与总长度值相加),例如“$ (“span”).eq (0);”,jQuery的DOM元素集合调用它的first方法可以返回一个只有此集合中首个DOM元素的jQuery集合,jQuery的DOM元素集合调用它的last方法可以返回一个只有此集合中最后一个DOM元素的jQuery集合,jQuery的DOM元素集合调用它的siblings方法可以返回一个跟此集合中所有DOM元素同级别的其它DOM元素所组成的jQuery集合(一般用来做排它),jQuery的DOM元素集合调用它的children方法可以返回一个此集合中所有DOM元素的传入选择器字符串所指代的子代DOM元素所组成的jQuery集合(当不传参时,返回值是一个所有子代DOM元素所组成的jQuery集合),例如“$ (“.nav>li”).children (“.sub”);”,jQuery的DOM元素集合调用它的parents/find方法可以返回一个此集合中所有DOM元素的传入选择器字符串所指代的上/下级DOM元素所组成的jQuery集合,例如“$ (“.infoDel”).parents (“.info”);”,jQuery的DOM元素集合调用它的hasClass方法可以检测此集合中所有DOM元素是否含有所传入的类名字符串,返回值是true/false,当未传参时,返回值是false,jQuery的DOM元素集合调用它的prev/next方法可以返回一个此集合中所有DOM元素紧邻的上/下一个同级别DOM元素所组成的jQuery集合

四、jQuery.js中事件的绑定

jQuery.js中有两种绑定事件方式,第一种方式是利用jQuery的DOM元素集合调用它的去掉on的事件名称来绑定,然后传入一个回调函数即可,例如“$ (“button”).click (function () {alert (“hello lnj”);} );”,优点是在调用去掉on的事件名称的时候编辑器会给予提示,所以编码效率略高,还不容易写错,缺点是部分JS事件在jQuery.js中没有实现,所以不能绑定,第二种方式是利用jQuery的DOM元素集合调用它的on方法来绑定,然后传入参数1去掉on的事件名称字符串和参数2回调函数即可,例如“$ (“button”).on (“click”, function () {alert (“hello click1”);} );”,优点是所有的JS事件都可以绑定,缺点是事件名称是以字符串的形式传入,编辑器不会给予提示,所以编码效率略低,还容易写错,以上这两种绑定方式都会给此jQuery的DOM元素集合所包含的所有DOM元素都绑定上相应事件,返回值是调用者,所传入回调函数的作用域中的this指针指代的是触发此事件的DOM元素,当使用这两种绑定方式给某个jQuery的DOM元素集合绑定多个同名事件时,不会发生覆盖,并且触发的顺序是正向的,由于mouseover/mouseout事件无法阻止事件冒泡,所以在一个同时绑定了mouseover和mouseout事件的jQuery的DOM元素集合中,当鼠标从此集合所包含的DOM元素mouseover到其子代DOM元素时,会先触发其mouseout事件,后触发其mouseover事件(冒泡所导致),当再从其子代DOM元素mouseover到此DOM元素时,会先触发其mouseout事件(冒泡所导致),后触发其mouseover事件,而mouseenter/mouseleave事件则可以阻止事件冒泡(推荐),给jQuery的DOM元素集合所绑定的hover事件的触发条件是鼠标移入/出此集合所包含的DOM元素(可传入一/两个回调函数),例如“$ (“.father”).hover (function () {console.log (“father被移入了”);}, function () {console.log (“father被移出了”);} );”,“$ (“.father”).hover (function () {console.log (“father被移入移出了”);} );”,给jQuery的window对象集合所绑定的scroll事件的触发条件是此浏览器窗口的滚动条发生滚动,给jQuery的input输入框/textarea/select元素集合所绑定的change事件的触发条件是此集合所包含的单/多行文本输入框中的内容发生改变并失去焦点(只有手动输入的才有效)/在此集合所包含的下拉菜单中选择了某个选项,由于change事件失去焦点才能触发,所以当想要实时监听单/多行文本输入框中的内容是否发生改变时,就不能使用change事件了,而且必须用使用事件委托,固定写法是例如“$ (“body”).delegate (“.comment”, “propertychange input”, function () {});(//为了做兼容性处理,所以绑定了propertychange和input两个事件)”,jQuery的DOM元素集合调用它的off方法可以移除给此集合中所有DOM元素所绑定的所传入的事件名称字符串,例如“$ (“button”).off ();(//不传参会移除所绑定的所有事件)”,“$ (“button”).off (“click”);”,“$ (“button”).off (“click”, function () {alert (“button”);} );(//参数2为参数1事件的回调函数,当给调用者绑定了多个同名的参数1事件时,可以定向移除某一个参数1事件)”,在jQuery中,阻止事件冒泡的方式是在传入的回调函数作用域的结尾处添加一句“return false;”/“event.stopPropagation ();(//需用形参event接收一下事件对象)”,让手动绑定的事件覆盖掉跟系统同名的事件(即阻止默认行为/移除默认事件)的方式是在传入的回调函数作用域的结尾处添加一句“return false;”/“event.preventDefault ();(//需用形参event接收一下事件对象)”,jQuery的DOM元素集合调用它的trigger/triggerHandler方法可以自动触发此集合中所有DOM元素所绑定的所传入的事件名称字符串,trigger方法会触发事件冒泡和默认事件,而triggerHandler方法则不会,例如“$ (“.son”).trigger (“click”);”,但是a元素比较特殊,即使调用了trigger方法也无法触发其默认事件,解决方式是在a元素内部再嵌套一个span元素,将a元素中的内容包起来,然后利用jQuery的span元素集合调用它的trigger方法并传入相应事件名称字符串即可,例如“$ (“span”).trigger (“click”);”,当想要自定义事件名称时,必须满足两个条件,一是此事件必须是调用on方法来绑定的,二是此事件必须调用trigger/triggerHandler方法来自动触发,例如“$ (“.son”).on (“myClick”, function () {alert (“son”);} );  $ (“.son”).trigger (“myClick”);”,jQuery的DOM元素集合调用它的on方法来给其绑定多个同名事件时,是存在事件命名空间的(即可以分别给此同名事件添加不同的备注名称),并且也可以调用trigger/triggerHandler方法来自动触发其中一个,例如“$ (“.son”).on (“click.zs”, function () {alert (“click1”);} );  $ (“.son”).on (“click.ls”, function () {alert (“click2”);} );  $ (“.son”).trigger (“click.ls”);”,当调用trigger方法自动触发某个DOM元素带有命名空间的事件时,其父DOM元素带有相同命名空间的同名事件也会被自动触发(冒泡),而其父DOM元素不带有相同命名空间的同名事件则不会被自动触发,当调用trigger方法自动触发某个DOM元素不带有命名空间的事件时,此DOM元素和其父DOM元素所有的同名事件都会被自动触发,在jQuery中,DOM元素可以将某个事件委托给其父DOM元素来监听,jQuery上级DOM元素集合调用它的delegate方法可以使参数1选择器字符串所指代的下级DOM元素委托此上级DOM元素来监听参数2事件字符串,触发后执行参数3回调函数(但无法监听hover事件,只能使用mouseenter和mouseleave事件来代替),适用于监听后期使用JS代码所动态添加的DOM元素,因为在入口函数执行的时候,此页面上的某些DOM元素就已经存在了,例如“$ (“ul”).delegate (“li”, “click”, function () {console.log ($ (this).html () );} );(//由于delegate方法的底层原理是event.target,所以click事件其实是绑定给了ul元素,这里的this指针指的是触发click事件的那个li元素,也就是将click事件冒泡给ul元素的那个li元素)”,jQuery的DOM元素集合调用它的one方法可以给此集合中所有DOM元素绑定只能触发一次的事件,例如“$ (“.wolfImage”).one (“click”, function () {});”

五、jQuery.js中的transition和animation

jQuery的DOM元素集合调用它的show/hide/toggle方法可以给此集合中所有DOM元素的display属性设置transition并设置display值为auto/none/切换show和hide的状态,例如“$ (“div”).show (1000, “linear”, function () {alert (“显示的transition执行完毕”);} );(//参数1毫秒值代表transition执行的时长,也可以换成“slow”/“normal”/“fast”,参数2为可选参数,代表transition执行的节奏,默认为“swing”,慢快慢,参数3回调函数在transition执行完毕后执行)”,jQuery的DOM元素集合调用它的slideDown/slideUp/slideToggle方法可以给此集合中所有DOM元素的display和height属性设置transition并设置它俩的值为auto和其本来的值/none和0/切换slideDown和slideUp的状态,用法同上,jQuery的DOM元素集合调用它的stop方法可以立即停止此集合中所有DOM元素当前的transition,并继续执行后续的transition(不传参/传入一/两个false),也可以立即停止当前和后续的transition(传入一个true/一个true一个false),也可以立即完成当前的transition,并继续执行后续的transition(传入一个false一个true),还可以立即完成当前的transition,并停止后续的transition(传入两个true),由于jQuery的transition中存在队列,即只有前一个transition执行完毕,后一个transition才会执行,所以当想要停掉上一个未完成的transition时,在执行当前这个transition之前调用一下stop方法即可(推荐),例如“$ (.sub).stop ();”,jQuery的DOM元素集合调用它的fadeIn/fadeTo/fadeOut/fadeToggle方法可以给此集合中所有DOM元素的display和opacity属性设置transition并设置它俩的值为auto和其本来的值/auto和所传入的值/none和0/切换fadeIn和fadeOut的状态,例如“$ (“div”).fadeTo (1000, 0.2, “linear”, function () {alert (“淡入到0.2完毕”);} )(//0.2代表opacity值)”,“$ (“.ad”).stop ().slideDown (1000).fadeOut (1000).fadeIn (1000);(//由于存在transition队列,所以我们可以通过链式调用来设置多个transition,事先stop一下只是为了规避一些隐含的bug,不影响效果)”,jQuery的DOM元素集合调用它的animate方法可以给此集合中所有DOM元素的一/多个行内样式属性设置animation(当设置多个时,多个行内样式属性的animation会同时执行),例如“$ (“.two”).animate ({width: 500}, 1000, “linear”, function () {alert (“自定义animation执行完毕”);} );(//参数1也可传入比如“{width: “+=100”}(//意思是在原基础上加100)”/“{width: “hide”/“show”/“toggle”}”)”,jQuery的DOM元素集合调用它的delay方法可以让此集合中所有DOM元素延迟传入的毫秒值再执行之后的animation,例如“$ (“.one”).animate ({width: 500}, 1000).delay (2000).animate ({height: 500}, 1000);”,jQuery.fx对象修改它的off属性值可以关闭此页面上所有的animation,格式为“jQuery.fx.off = true;(//默认值是false)”,jQuery.fx对象修改它的interval属性值可以设置此页面上animation的显示帧速,例如“jQuery.fx.interval = 100;(//默认值是13,值越大越卡,越小越流畅,也越消耗浏览器的性能)”

六、mCustomScrollbar.js插件

此插件是一个基于jQuery.js的插件,可以美化滚动条的样式,先上官网manos.malihu.gr/jquery-custom-content-scroller,找到download,下载到本地并解压缩,引入文件的顺序为jquery.mCustomScrollbar.css、自己的index.css(因为在我们自己的index.css中有可能去操作jquery.mCustomScrollbar.css)、jQuery.js、jquery.mCustomScrollbar.concat.min.js、自己的index.js,然后找到页面上的“Initialization”标题,直接调用它封装好的函数就可以了,例如“$ (“.content”).mCustomScrollbar ();(//“.content”代表某个DOM元素)”,然后找到“Initialize via HTML”标题,就可以看到在HTML结构代码上如何使用了,找到想美化的那个HTML标签,给它添加一个自定义的HTML属性,叫做data-mcs-theme属性,取值有很多可以选择,找到页面上的“view demo”标题,点击“Scrollbar themes”按钮,就可以看到不同的取值分别代表不同的样式,当想要修改滚动条的宽度时,可以阅读主页上的“Scrollbar markup”标题下的内容,当想要把滚动条的宽度改为8px时,需要在我们自己的index.css上添加上一句“._mCS_1 .mCSB_dragger .mCSB_dragger_bar {width: 8px;}”即可,由于在国内用此插件的人比较多,所以网上也有很多中文的文档,可以自己百度一下中文的文档

七、jQuery.js的原理

jQuery的本质是一个闭包,即定义在一个立即执行的匿名函数内部的子函数,好处是当引入多个类库/框架时,可以避免这些类库/框架中所定义变量的命名冲突,在此立即执行的匿名函数的作用域中,必须通过“window.jQuery = jQuery;”的方式将此局部jQuery函数转成全局函数,jQuery函数所在的立即执行的匿名函数之所以给自己传入一个window对象一是为了方便后期压缩代码,因为形参就可以用一个字母例如“w”来代替了,二是为了提升查找的效率,因为当自己的作用域中有window对象时,使用自己作用域中的就可以了,就不用沿着作用域链去查找了,jQuery函数所在的立即执行的匿名函数之所以要用形参给自己接收一个undefined,一是为了方便后期压缩代码,二是为了保证内部使用的undefined不被修改,因为在IE9以下的低级浏览器中,undefined是可以被修改的,例如“undefined = 998;(//在IE9以下的低级浏览器中,undefined就变成了998)”,所以需要接收一个正确的undefined,jQuery的精髓是免用new,直接“jQuery ();”就可以return一个init函数(类)的实例对象,但是为了使此实例对象可以调用jQuery.prototype中所定义的各种方法,必须在最后加上一句“jQuery.prototype.init.prototype = jQuery.prototype;(//将init类的prototype对象指向了jQuery类的prototype对象)”,这样一来,我们所获取到的实例对象就可以调用jQuery.prototype中所定义的各种方法了

八、AJAX

“器”这个词在硬件领域指的是一个看得见、摸得着的实物,在软件领域指的是“程序”,同理,服务器在硬件领域指的是一台24小时不断电、不关机,并且提供了某种服务功能的超级电脑,而在软件领域指的是提供了某种服务功能的程序,根据所提供服务的不同又分为文件服务器、邮件服务器、和web服务器(例如Apache、IIS、Tomcat、Nginx、和NodeJS)等,所以,提供管理网站服务的软件/安装了此软件的电脑都可以叫做web服务器,WAMPServer指的就是W(Windows操作系统)+A(Apache,世界排名第一的web服务器,特点是简单、速度快、性能稳定)+M(MySQL数据库,一款开源免费的数据库软件,特点是体积小、速度快、使用成本低)+P(php解释器,php即Personal home page Hypertext Preprocessor,就是个人主页超文本预处理程序,可以直接将代码嵌入HTML文档中执行,特点是简单易学,容易上手),安装Apache的方法是,先双击WAMPServer安装包,然后选择语言,只有English,没有Chinese,点击OK->Next->Next,选择安装路径(路径中一定不要出现中文,否则以后会有一些未知的bug,比如系统托盘区的图标不变绿),然后点击Next->Next,点击install开始安装,然后点击“是”选择浏览器,任意一个浏览器都可以,比如找到桌面,选择谷歌浏览器,点击“打开”,再点“是”,再找到桌面,再选择谷歌浏览器,再点击“打开”,然后点击Next->Finish安装完毕,然后双击打开WAMPServer,在系统托盘区会出现一个图标,此图标一开始是红色的,然后变为黄色的,最后会变为绿色的,只有它变为绿色的才代表着此软件正常的运行了,此电脑就可以提供web相关的服务了(即变成了一台本地web服务器),可以测试访问一下,打开web浏览器,访问web服务器默认的ip地址“127.0.0.1”,就看到显示的内容了,由于php是服务端编程语言,所以php代码只能使用php解释器配合web服务器(例如Apache)来解释执行,当我们经由webstorm使用web浏览器来打开.php文件时,虽然webstorm默认就是服务端的环境,但是也是无法解释执行php代码的,页面会报“502 bad gateway”的错误,所以我们必须先双击运行WAMPServer软件,然后将.php文件放在WAMPServer软件安装目录中名叫“www”的文件夹中,然后再使用web浏览器访问web服务器的ip地址(即向web服务器发送请求报文),但是默认打开的是“www”文件夹中的“index.php”文件,当将此文件更改一下名称时,再次使用web浏览器访问web服务器的ip地址,就默认进入“www”文件夹了,然后从此文件夹的目录中就可以找到我们放进去的那个.php文件了,找到之后一点击就打开了,就可以将此.php文件中php代码的执行结果(即所输出的数据)渲染出来了,.php文件的名称不能有中文,php的代码都需要写在“<?php”和“?>”之间,“?>”可写可不写,php的大部分基础语法跟JS的差不多,php中的注释跟JS中的注释长得一模一样,功能也一模一样,php中定义变量的格式为“$变量名 = 取值;”,输出(返回)变量的格式为“echo $变量名;”,php中也可以定义集合,即数组/字典(对象),定义数组的格式为“$arr = array (1, 3, 5);”,输出(返回)数组的格式为“print_r ($arr);”,输出(返回)数组中某个元素的格式为“echo $arr[1];”,定义字典(对象)的格式为“$dict = array (“name”=> “lnj”, “age”=> “33”);”,输出(返回)字典(对象)的格式为“print_r ($dict);”,输出(返回)字典(对象)中某个元素的格式为“echo $dict[“name”];”,php中的分支循环语句跟JS中的也类似,例如“if ($age >= 18) {echo “成年人”;} else {echo “未成年人”;}”,“$res = ($age >= 18) ? “成年人”: “未成年人”;”,“switch ($age) {case -1: echo “非人类”;  break;  case 18: echo “成年人”;  break;  default: echo “未成年人”;  break;}”,“$arr = array (1, 3, 5);  for ($i = 0; $i < count ($arr); $i++) {echo $arr[$i];  echo “<br>”;}”,“$index = 0;  while ($index < count ($arr) ) {echo $arr[$index];  echo “<br>”;  $index++;}”,php中有超全局变量$_GET、$_POST、和$_FILES,前两个分别用来接收web浏览器通过get和post请求所提交过来的数据(文件除外),第三个是用来接收web浏览器所提交过来的文件(例如.jpg/.mp4文件),一定注意文件/文件夹的名称不能出现中文,否则会乱码/报错,因为web服务器不支持中文,然后web服务器会默认将所接收到的文件保存到安装目录的tmp文件夹(临时文件夹),当保存了一会之后仍然未使用时,就会自动删除,以节约web服务器的存储空间,超全局变量中所保存的数据都是字典(对象),$_FILES字典访问它的upFile属性可以返回上传文件所对应的字典,upFile字典访问它的name属性可以返回上传文件的名称字符串,upFile字典访问它的tmp_name属性可以返回上传文件被保存的临时路径字符串,调用move_uploaded_file函数可以将参数1所上传的文件名称字符串移动到参数2新路径字符串,例如“move_uploaded_file ($filePath, “./source/”.$fileName);(//在php中用“.”来拼接字符串)”,调用sleep函数可以停留传入的秒数值再执行后面的代码,例如“sleep (5);”,调用file_get_contents函数可以返回传入的文件URL字符串中此文件中的数据字符串,例如“file_get_contents (“info.xml”);(//当所返回的数据中有中文时,可能会出现乱码问题,只需要在php文件顶部添加上一句“header (“content-type:text/html; charset=utf-8”);(//html也可以换成xml)”即可,当所返回的是JSON时,就不用添加了)”,调用json_encode函数可以返回传入字典被转成的JSON,当此函数执行失败时,返回值是false,使用web浏览器访问html网页的过程是首先根据在web浏览器地址栏所输入的URL向web服务器发送请求报文,web服务器(例如Apache)接收到之后会先对请求报文进行处理,然后再将html文件通过响应报文返回给web浏览器,最后web浏览器再将所返回的html文件渲染出来即可,向web服务器发送请求与提交数据(即与web服务器交互)的过程也是首先根据web浏览器地址栏的URL/请求头中所保存的内容,向web服务器发送请求报文,web服务器(例如Apache)接收到之后会先对请求报文进行处理,然后再在此web服务器上执行经过解释器所解释后的服务端代码(例如php代码),然后再将此代码的执行结果(即所输出的数据)通过响应报文返回给web浏览器,最后web浏览器再将所输出的数据渲染出来即可,默认情况下web服务器对需要上传的文件是有限制的,当想要修改此限制时,可以修改“php.ini”文件,路径是WAMPServer安装目录->bin->apache->apache2.4.23->bin->php.ini,找到之后最好用编辑器打开,不要用记事本,容易产生编码问题,可以搜索以下几项做一下更改,file_uploads = On,是否允许web浏览器上传文件,取值是On/Off,默认值是On,upload_max_filesize = 2M,web浏览器上传文件的最大限制,可以改成2048M,post_max_size = 8M,允许web浏览器通过post请求所提交的最大数据,可以改成2048M,max_execution_time = 120,web服务器上脚本最长的执行时间,单位为秒,可以改成3000,max_input_time = 60,web服务器接收所提交数据的时间限制,单位为秒,可以改成3000,memory_limit = 128M,允许web服务器最大的内存消耗,可以改成2048M,全都修改完之后保存一下,然后重启一下WAMPServer,只需要单击系统托盘区的此软件图标,然后单击“Restart All Services”就可以了,AJAX(Asynchronous JavaScript and XML)即异步的JS和XML,并不是一门新的编程语言,而是在不重新加载整个html页面的情况下与web服务器交换数据并更新部分html页面的技术,使用AJAX总共分为五步,第一步new一个AJAX异步对象(XMLHttpRequest对象/ActiveXObject对象),XMLHttpRequest对象兼容除了IE5和IE6之外的所有浏览器,IE5和IE6使用ActiveXObject对象,例如“var xmlhttp;  if (window.XMLHttpRequest) {xmlhttp = new XMLHttpRequest ();} else {xmlhttp = new ActiveXObject (“Microsoft.XMLHTTP”);}”,第二步设置向web服务器提交数据的请求方式和URL,例如“xmlhttp.open (“get”, “04-ajax-get.php?userName=zs&userPwd=321”, true);(//参数1传入请求的类型字符串,大小写均可,参数2传入请求的url字符串,即文件在web服务器的路径字符串,参数3传入true/false,表示异步/同步,由于AJAX存在的意义就是发送异步请求,所以参数3永远传true)”,当需要发送的是post请求时,需要再写一句“xmlhttp.setRequestHeader (“Content-type”, “application/x-www-form-urlencoded”);(//设置请求头)”,第三步是发送请求,例如“xmlhttp.send ();(//get请求,不用传参,因为在第二步时会将需要提交的数据附加到URL后面的“?”后面)”,“xmlhttp.send (“userName=zs&userPwd=321”);(//post请求)”,异步对象调用它的abort方法可以中断请求,例如“xmlhttp.abort ();”,第四步是监听异步对象请求状态码的变化,给异步对象所绑定的onreadystatechange事件的触发条件是此异步对象的readyState值发生了改变,异步对象访问它的readyState属性可以返回此异步对象的请求状态码(数值),0代表请求未初始化,1代表跟web服务器的连接已建立,2代表web服务器已接收到请求,3代表web服务器正在处理请求,4代表web服务器已将请求处理完毕,且响应已就绪,异步对象访问它的status属性可以返回web服务器的响应状态码(数值),只要此响应状态码是大于等于200且小于300或者是304(304代表返回本地的缓存数据)就代表响应成功,除此之外的响应状态码就代表响应失败,当所请求的url不存在时,就会响应失败,例如“xmlhttp.onreadystatechange = function () {if (xmlhttp.readyState === 4) {if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status === 304) {console.log (“获取到web服务器所输出的数据”);} else {console.log (“没有获取到web服务器所输出的数据”);} } }”,第五步是处理web服务器所输出的数据,就是执行触发onreadystatechange事件之后的回调函数,异步对象访问它的responseText属性可以返回web服务器所输出的数据字符串(非XML时使用),所返回的数据会随着web服务器所输出数据的变化而变化,但在IE浏览器中,由于IE浏览器会缓存通过get请求从web服务器所获取到的内容,所以在通过AJAX发送get请求时,当所请求的URL没有发生变化时,IE浏览器就不会再次向web服务器发送get请求,而是直接从IE浏览器的缓存中返回上次通过该URL从web服务器所获取到的数据,这样一来,无论怎么修改web服务器所输出的数据,IE浏览器都会将首次所获取到的结果直接返回,不会返回web服务器所输出的最新数据,从而导致数据的不同步,当想要返回web服务器所输出的实时变化的数据时,必须保证每一次发送get请求时URL都有变化,我们可以在URL后面附加上比如“?t=一个随机数(随机因子)”,这样一来,web服务器不会做任何处理,并且可以返回web服务器所输出的最新数据,随机数可以使用“Math.random ();”/“new Date ().getTime ();”,例如“xmlhttp.open (“GET”, “05-ajax-get.txt?t=”+ (new Date ().getTime () ), true);”,异步对象访问它的responseXML属性可以返回web服务器所输出的XML文档对象(即document对象,所返回的此document对象可以访问/调用JS中相应的属性/方法来返回相应的数据),例如“xmlhttp.responseXML.querySelector (“age”).innerHTML;”,XML(Extensible Markup Language)是可扩展标记语言,XML文件是有固定格式的,第一行必须写上“<?xml version=“1.0”encoding=“UTF-8”?>”,version值是XML的版本号,encoding值是XML的字符集,一般情况下字符集都是UTF-8,第一行写完之后,还必须有一对根标签,只不过XML的根标签可以随意命名,例如“<abc></abc>”,所有数据都必须嵌套在这对根标签中才有效,而这对根标签中的每一条数据也都是需要嵌套在一对随意命名的双标签中的,jQuery类对象调用它的ajax方法可以通过HTTP请求来获取web服务器所输出的数据,格式为“$.ajax ({配置对象});”,在配置对象中可以添加url属性,取值是需要发送请求的URL字符串,可以添加timeout属性,取值是毫秒值,当请求时长超过此毫秒值时,就中断请求,可以添加type属性,取值是“get”(默认值)/“post”,可以添加data属性,取值是一个对象/字符串(例如“userName=lnj&userPwd=123456”),当取值是一个对象时,会自动转成字符串,当取值是一个对象并且value是一个数组时,例如“{foo: [“bar1”, “bar2”]}”,会转成“&foo=bar1&foo=bar2”,当需要发送的是get请求时,会自动将此data值附加在此url值之后,可以添加dataType属性,取值是“xml”/“html”/“script”/“json”/“jsonp”/“text”,可以添加jsonp属性,取值是在一个jsonp请求中,用来取代URL后面所附加的“callback=随机函数名”中的callback部分的自定义名称字符串,可以添加jsonpCallback属性,取值是在一个jsonp请求中,用来取代URL后面所附加的“callback=随机函数名”中的随机函数名部分的自定义名称字符串,可以添加complete方法,取值是在请求完成后无论响应成功/失败都会执行的回调函数“function (XMLHttpRequest, textStatus) {}”,形参textStatus接收到的是描述成功请求类型的字符串,可以添加success方法,取值是在请求完成并响应成功后所执行的回调函数“function (data, textStatus) {}”,形参data接收到的是web服务器所输出的根据配置对象中的dataType值进行处理后的数据,可以添加error方法,取值是在请求完成但响应失败后所执行的回调函数“function (XMLHttpRequest) {}”,会话跟踪技术分为web浏览器的和web服务器的,web浏览器的是cookie,web服务器的是session,由于web前端属于web浏览器端,所以我们只需要了解cookie就可以了,cookie是此html网页保存到此web浏览器中的数据(key-value格式的文本信息),web浏览器默认不会保存任何的cookie,也不能一次性保存多条cookie,当想要保存多条cookie时,只能一条一条的设置,cookie有大小和条数的限制,根据web浏览器的不同,条数通常限制在20条到50条左右,为了兼容所有web浏览器,一般情况下我们不会设置超过20条,总大小限制在4KB左右,并且每次都会携带在HTTP头中发送到web服务器,所以当使用cookie保存过多的数据时,就会带来性能问题,cookie经常用于存储用户的登录状态,由于会把用户的登录状态发送到web服务器,所以在本地验证完,在web服务器可以进一步的验证,这样就达到了双重验证的效果,谷歌浏览器不支持JS在本地操作cookie(火狐支持),只有在web服务器的环境下才可以操作cookie,document对象访问它的cookie属性可以返回/设置此web浏览器中所保存的cookie,例如“document.cookie = “age=33;”;”,设置完之后,我们可以通过F12(开发者工具)->Application->Cookies,点击展开,然后再点击此网址来查看,web浏览器中所保存cookie的生命周期默认情况下就是一次会话,关闭此web浏览器(注意是此web浏览器,不是此标签页)即被清除,还可以通过拼接“expires=过期时间”字符串来手动设置过期时间,例如“var date = new Date ();  date.setDate (date.getDate () + 1);  document.cookie = “age=33;expires=”+ date.toGMTString () + “;”;”,当没有到达所设置的过期时间时,即使关闭了此web浏览器,再打开此web浏览器此cookie还是存在,当到达了所设置的过期时间时,即使没有关闭此web浏览器,此cookie也会被立即清除,某一个html文件给此web浏览器所设置的cookie可以被在此二级域名文件夹下跟此html文件同级/其下级目录的其它html文件所访问,当也想被在此二级域名文件夹下其上级目录的其它html文件所访问时,就需要在设置cookie的时候在结尾处添加一个path属性,取值是此二级域名文件夹的根目录,例如“document.cookie = “name=zs;path=/;”;”,由于在一个网站文件夹中包括若干个二级域名文件夹,例如“www.it666.com”和“edu.it666.com”就是在同一个网站文件夹中的两个不同的二级域名文件夹,所以,当想要让某一个二级域名文件夹内的html文件给此web浏览器所设置的cookie能够被其它二级域名文件夹内的html文件所访问时,就需要在结尾处再添加一个domain属性,取值是此网站文件夹的根目录(即根域名),以后当我们想要保存一个cookie时,使用这种形式即可,例如“document.cookie = “name=zs;path=/;domain=it666.com;”;”,document对象访问它的domain属性可以返回此html网页的web服务器域名(主机名)字符串,当想要封装一个基于jQuery.js的插件时,则插件名称的固定格式为“jQuery.插件的作用.js”,例如“jQuery.cookie.js”,插件里边固定的写法为“;() ();”,在两个小括号中写一个立即执行的匿名函数(即闭包),并传入jQuery和window,例如“;(function ($, window) {}) (jQuery, window);”,H5新增的存储方案是sessionStorage和localStorage,跟cookie一样,sessionStorage和localStorage也是此html网页保存到此web浏览器中的数据(key-value格式的文本信息),但它俩仅仅是保存到了此web浏览器中,不参与跟web服务器的通信,而且它俩的大小均限制在5M左右,详情可参考网址“dev-test.nemikor.com/web-storage/support-test/”,sessionStorage的生命周期是仅在此标签页下有效,关闭此标签页/web浏览器后就会被清除,而且不能设置过期时间,经常用于存储表单数据,因为当用户注册某个东西的时候,就会填表单,填表单时有可能填完了第一页还有第二页,数据就会比较大,所以就需要大容量,并且在没有关闭此标签页的情况下,当返回上一页时,上一页的数据会仍然存在,当关掉了此标签页时,表单中的数据就清空了,localStorage除非被清除,否则会永久保存,经常用于存储购物车的一些数据,因为当用户在web浏览器上向购物车里添加了很多商品时,在没有买单的情况下,当关闭了此web浏览器时,下一次用户再通过此web浏览器打开购物车页面,他上一次向购物车中所添加的商品仍然会存在,容量大并且永久存储,通过cookie属性、sessionStorage对象、和localStorage对象三种方式,切记都不能将敏感数据直接存储到web浏览器,否则别人就有可能通过此web浏览器的F12->Application,然后点击cookie/sessionStorage/localStorage来修改我们的数据,sessionStorage/localStorage对象调用它的setItem方法可以给此web浏览器新增/修改一条sessionStorage/localStorage,例如“sessionStorage.setItem (“name”, “lnj”);(//以JSON的形式)”,sessionStorage/localStorage对象调用它的getItem方法可以返回此web浏览器sessionStorage/localStorage中传入key所对应的value,例如“sessionStorage.getItem (“name”);”,sessionStorage/localStorage对象调用它的removeItem方法可以删除此web浏览器sessionStorage/localStorage中传入key所指代的键值对,例如“sessionStorage.removeItem (“name”);”,sessionStorage/localStorage对象调用它的clear方法可以清空此web浏览器sessionStorage/localStorage中保存的所有数据,例如“sessionStorage.clear ();”,同源策略(Same origin policy)是一种约定,它是web浏览器最核心最基本的安全功能,超文本传输协议、一级域名、二级域名、和端口号都相同的URL就叫做同源的URL,否则就叫做跨域的URL,例如在URL“http://www.it666.com:80/index.html”中,“http://”就叫做超文本传输协议,“it666.com”就叫做一级域名,“www.”就叫做二级域名,“:80”就叫做端口号,“/index.html”就叫做资源路径,为了提升html网页的性能,html网页和数据一般都是单独存储在不同的web服务器上,但web浏览器只允许AJAX请求同源URL的数据,不允许请求跨域URL的数据,跨域请求的解决方案是“JSONP(JSON with Padding,即填充式JSON)”、“document.domain+iframe”、“location.hash+iframe”、“window.name+iframe”、“window.postMessage”、和“flash等第三方插件”,但只有“JSONP”是目前常用的,由于通过<script>的src属性既可以引入本地的数据,还可以引入网络的数据,没有同源与否的限制,所以我们可以通过<script>的src属性来请求跨域的数据,让html网页从跨域的URL来获取数据的过程就叫做JSONP,通过JSONP从web服务器所获取到的一般都不会是一个“变量”字符串,而是一句带有参数的“函数的调用”字符串,这样一来,通过所获取到的数据就可以调用我们在本地所定义的函数,而传入的参数就是我们所需要的数据,但是问题是,我们在本地所定义的函数名称却有可能是变化的、不确定的,解决方案是在URL后面添加点参数,来动态的告诉web服务器我们在本地所定义的函数名称是什么,例如“<script src=“http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test”></script>”,然后后端代码可以“$cb = $_GET[“cb”];  echo $cb.“(666);”;(//在php中用“.”来拼接字符串)”,由于默认情况下多个<script>的执行是同步的,即只有前面的<script>执行完毕,后面的<script>才会执行,所以为了安全起见,请求跨域数据的<script>必须写到后面,但是当我们使用JS来动态的createElement script元素时,就不存在这个问题了,因为使用JS所动态createElement的script元素默认就是异步的,会在最后执行,例如“let oScript = document.createElement (“script”);  oScript.src = “http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test”;  document.body.appendChild (oScript);  function test (data) {console.log (data);}”,存储在硬盘(rom)中的一些永久性的数据就叫做静态数据,当计算机关闭之后再开启,静态数据依旧还在,只要你不主动删掉或者硬盘没坏,静态数据永远都在,在程序运行过程中,动态产生存储在内存(ram)中的临时性数据就叫做动态数据,当计算机关闭之后,这些临时性数据就会被清除,之所以不把所有的应用程序加载到硬盘中去执行,主要原因就是内存的访问速度比硬盘快N倍,静态数据是可以转成动态数据的,例如硬盘上存储的视频加载到播放软件上播放,动态数据也是可以转成静态数据的,例如拍照软件拍的一张照片写入到本地硬盘,将编译型语言编写好的代码通过编译工具编译之后存储在硬盘上的一个二进制文件就叫做应用程序,应用程序在操作系统中的一次执行过程就叫做进程,进程是系统进行资源分配和调度的基本单位,同一个应用程序在操作系统中每执行一次都会开启一个进程,并且所开启的多个进程的空间是相互独立的,互不影响的,所以应用程序和进程之间是一对多的关系,进程中的一个执行实例就叫做线程,线程是应用程序执行的最小单元,它是比进程更小的能独立运行的基本单位,在一个进程中有一个默认的线程,叫做主线程,主线程的作用是执行应用程序中的业务逻辑代码,除此之外,开发人员在编写应用程序的时候还可以手动创建一些其它的线程,所以进程和线程之间也是一对多的关系,例如启动迅雷这个应用程序,系统会创建一个迅雷进程,并且此迅雷进程会有一个默认的主线程,用于执行迅雷默认的业务逻辑,当我们利用迅雷同时执行多个下载任务的时候,迅雷就会创建多个线程,将不同的下载任务放到不同的线程中执行,当一个进程中只有一个线程并且有多个任务需要执行时,只有前一个任务执行完毕,后一个任务才能执行,这就叫做串行,当一个进程中有多个线程并且有多个任务需要执行时,就可以一个线程执行一个任务,多个线程都可以同时执行任务,这就叫做并行,JS是单线程的编程语言,之所以被设计成单线程的,是因为它作为web浏览器的脚本语言,主要的用途是与用户的互动,以及操作DOM元素,假如JS被设计成多线程的,当有一个线程要修改DOM元素中的内容,而另一个线程却要删除该DOM元素时,web浏览器就会有很复杂的同步问题,不知道该以哪个线程为准,正是由于JS是单线程的编程语言,所以JS代码都是串行的,当前面的代码没有执行完毕时,后面的代码就不能执行,并且JS代码分为同步代码和异步代码,只有“满足一定条件才可执行的回调函数”(比如事件所绑定的回调函数)是异步代码,除此以外的都是同步代码,在程序运行时,会先从上至下依次执行所有的同步代码,当遇到异步代码时,会将异步代码放到所有代码最后的事件循环中,当所有同步代码都执行完毕时,系统会不断检测事件循环中的异步代码是否满足条件,当满足条件时,就执行相应的回调函数,但是当在同一个回调函数中需要按照一定顺序执行很多回调函数时(即异步操作),势必就会出现回调函数的层层嵌套,当所嵌套的层数太多时,就会导致代码的阅读性和可维护性大大降低(即回调地狱),所以在ES6中就新增了一种异步编程的解决方案,即Promise类,new Promise所创建的实例对象就叫做Promise对象(ES6新增),创建Promise对象的格式为“new Promise (function (resolve, reject) {});”,所传入的回调函数不是异步的,是会立即执行的,形参resolve和reject接收到的是回调函数,在不调用resolve/reject回调函数时,自身的[[PromiseStatus]]/[[PromiseState]]值默认就是“pending”(代表默认状态),[[PromiseValue]]/[[PromiseResult]]值默认就是undefined,在调用resolve回调函数时(等价于Promise.resolve (参数);),当不传参/所传入的实参不是一个额外的Promise对象时,自身的[[PromiseStatus]]值是“resolved”/“fulfilled”(代表成功状态),自身的[[PromiseValue]]值是undefined/所传入的实参,当所传入的实参是一个额外的Promise对象时,自身的状态和[[PromiseValue]]值也会继承于所传入的实参,在调用reject回调函数时(等价于Promise.reject (参数);),自身的[[PromiseStatus]]值是“rejected”(代表失败状态),自身的[[PromiseValue]]值是undefined/所传入的实参,当一个Promise对象的状态一旦变为成功/失败时,就是永久性的,不会再发生变化了,Promise对象调用它的then方法可以监听调用者的成功/失败状态,在成功/失败状态下执行参数1/2回调函数,并且调用者的[[PromiseValue]]值也会传入参数1/2回调函数中,在没有传入参数2回调函数,并且参数1回调函数的返回值不是一个额外的Promise对象时,当调用者是成功状态时,then方法的返回值是一个继承了调用者状态并且[[PromiseValue]]值是参数1回调函数返回值的新Promise对象,当调用者是失败状态时,then方法的返回值是一个继承了调用者状态和[[PromiseValue]]值的新Promise对象,在传入了参数2回调函数,并且所执行的参数1/2回调函数的返回值不是一个额外的Promise对象时,then方法的返回值是一个成功状态并且[[PromiseValue]]值是参数1/2回调函数返回值的新Promise对象,在无论有没有传入参数2回调函数,只要所执行的参数1/2回调函数的返回值是一个额外的Promise对象时,then方法的返回值是一个继承了此额外Promise对象状态和[[PromiseValue]]值的新Promise对象,当调用then方法时,还可以捕获上一个调用者在调用then/catch方法时所出现的错误,并将所捕获到的错误传入参数2回调函数中,并执行此参数2回调函数,Promise对象调用它的catch方法可以监听调用者的失败状态,在失败状态下执行所传入的回调函数,并且调用者的[[PromiseValue]]值也会传入此回调函数中,当传入回调函数的返回值是一个额外的Promise对象时,catch方法的返回值是一个继承了此额外Promise对象状态和[[PromiseValue]]值的新Promise对象,当传入回调函数的返回值不是一个额外的Promise对象时,catch方法的返回值是一个成功状态并且[[PromiseValue]]值是传入回调函数的返回值的新Promise对象,catch方法其实是then方法的语法糖,相当于“then (undefined, () => {})”,对于一个失败状态的Promise对象,必须予以监听,否则就会报错,而成功状态的Promise对象则无所谓,所以,当我们想要分别调用then和catch方法来监听调用者成功/失败的状态时,建议使用链式编程合并成一句代码来写,一旦分成了两句代码来写,当调用者是失败状态时,then方法的返回值是一个继承了调用者状态的新Promise对象,这样一来,此失败状态的新Promise对象就没有得到监听,进而就报错了,当调用catch方法时,还可以捕获上一个调用者在调用then/catch方法时所发生的错误,并将所捕获到的错误传入回调函数中,并执行此回调函数,例如“let p1 = new Promise (function (resolve, reject) {resolve ();} );  p1.then (function () {console.log (“成功”);  xxx} ).catch (function (e) {console.log (“失败”, e);} );(//控制台会打印“失败 ReferenceError: xxx is not defined”)”,综上所述,可以根据Promise对象的成功/失败状态并调用then/catch方法来实现用同步流程表示异步操作,以此避免回调函数层层嵌套的问题,由于JS是单线程的,所编写的代码都是串行的,所以一旦前面的代码出现错误,程序就会被中断,后续的代码就不会执行了,当是自身编写代码的问题时,就手动修复bug,当是外界的一些可预见的错误时,就可以使用try catch来捕获错误,既可以保证程序不被中断,增强程序的容错性和健壮性,还可以记录错误原因,以便于后续优化、迭代、更新,try catch是一个整体,不能分开,必须同时出现,格式为“try {可能遇到错误的代码;} catch (e) {捕获错误的代码块;}”,当try中的代码没有出现错误时,就会正常执行,而catch中的代码就不执行了,当try中的代码出现了错误时,catch中的代码就会执行,并把错误的原因传递给catch中的形参e,Promise类对象调用它的all方法可以在传入一个由Promise对象所组成的数组时,当所有的元素都是成功状态时,返回值是一个成功状态并且[[PromiseValue]]值是所有元素的[[PromiseValue]]值所组成数组的新Promise对象,当所有的元素不都是成功状态时,返回值是一个失败状态并且[[PromiseValue]]值是首个失败状态元素的[[PromiseValue]]值的新Promise对象,all方法的应用场景是当进行批量加载时,要么一起成功,要么一起失败,其实调用all方法时也可以传入一个普通数组(即非Promise对象所组成的数组),此时all方法的返回值是一个成功状态并且[[PromiseValue]]值是所传入数组的Promise对象,Promise类对象调用它的race方法可以在传入一个由Promise对象所组成的数组时,返回值是一个继承了状态变化最快元素状态和[[PromiseValue]]值的新Promise对象,race方法的应用场景是接口调试,超时处理,全局对象调用它的fetch方法可以实现基于Promise的AJAX(ES6新增),可以传入一个URL字符串和一个对象,例如“fetch (“http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34”, {method: “get”});”,“fetch (“http://127.0.0.1/jQuery/Ajax/41.php”, {method: “post”, body: JSON.stringify ({teacher: “lnj”, age: 34}) });”,返回值是一个成功状态并且[[PromiseValue]]值是Response对象的Promise对象,Response对象调用它的text方法可以返回一个成功状态并且[[PromiseValue]]值是web服务器所输出数据的新Promise对象,Response对象调用它的json方法可以返回一个web服务器响应状态并且[[PromiseValue]]值是web服务器所输出JSON被转成的JS对象的新Promise对象,axios.js是一个基于Promise的HTTP类库,即网络请求插件,可以在web浏览器和NodeJS中使用,axios.js插件跟fetch方法的功能是一样的,但axios.js插件更完善也更安全,建议使用axios.js插件就可以了,可以在GitHub上下载此插件,解压之后,在里面的dist文件夹中,就会看到axios.js和axios.min.js文件,将它俩复制到我们自己的项目中就可以了,可以在“www.kancloud.cn/yunye/axios/234845”网址查看一下它的中文文档,axios类对象调用它的get/post方法可以返回一个web服务器响应状态并且[[PromiseValue]]值是Response对象的Promise对象,例如“axios.get (“http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34”);(//可以改写为“axios.get (“http://127.0.0.1/jQuery/Ajax/41.php”, {params: {teacher: “lnj”, age: 34} });”)”,“axios.post (“http://127.0.0.1/jQuery/Ajax/41.php”, {teacher: “lnj”, age: 34});”,Response对象访问它的data属性可以返回web服务器所输出的数据即result对象(当数据是JSON时会自动转成JS对象),axios类对象调用它的all方法可以同时执行多个“axios.get ();”/“axios.post ();”(即同时执行多个并发请求),格式为“axios.all ([axios.get (‘/user/12345’), axios.get (‘/user/12345/permissions’)] ).then (axios.spread (function (result1, result2) {console.log (result1, result2);} ) );(//result1和result2接收到的分别是第一个和第二个get请求所获取到的Response对象)”,在企业开发中,项目分为开发和部署两个阶段,在这两个阶段中,项目所存储的位置是不同的,项目上线前存储在企业内部的测试服务器上,项目上线后存储在企业的正式服务器上(例如上线前URL是“http://127.0.0.1/jQuery/Ajax/41.php”,上线后URL是“http://192.199.13.14/jQuery/Ajax/41.php”),当每次向web服务器发送请求时,假如都将所请求的完整URL写在请求中,那么当项目上线时,就需要大量修改所请求的URL,所以为了解决这个问题,我们可以设置一个全局的URL根地址,等到项目上线时只需要修改根地址即可,例如“axios.defaults.timeout = 2000;(//设置请求的超时时间,当两秒钟之内服务器没有返回数据时,就会报错)  axios.defaults.baseURL = “http://127.0.0.1”;(//设置全局的URL根地址)  axios.post (“/jQuery/Ajax/41.php”, {teacher: “lnj”, age: 34}).then (function (res) {console.log (res.data);} ).catch (function (e) {console.log (e);} );”,Symbol()是ES6中新增的基本数据类型,由于Symbol不是函数,所以前面不能加new,Symbol()就代表一个独一无二的值,数据类型是symbol,由于Symbol()和Symbol()分别是两个独一无二的值,所以Symbol()和Symbol()不全等,symbol类型的数据可以转成字符串和布尔类型的数据,但不能转成数值类型的数据,symbol类型的数据也不能做任何运算,当给第三方的插件/框架动态的添加了重名的属性/方法时,势必就会将此插件/框架中原有的属性/方法覆盖掉,所以为了避免这种情况的发生,插件/框架的作者/使用者就可以使用Symbol()来动态的添加属性/方法,也可以同时在Symbol()的小括号中添加一个字符串来设置一个标记,这个标记仅仅是为了便于区分,没有任何其它含义,当想要在一个对象的内部手动添加symbol类型的属性/方法时,必须首先在此对象的外部将Symbol()保存到一个变量中,然后在此对象的内部再给此变量加一个中括号来充当属性/方法的名称,并且当想要访问/调用它们时,不能使用“.”的方式,只能使用中括号包裹相应变量的方式,例如“let name = Symbol(“name”);  let say = Symbol(“say”);  let obj = {[name]: “lnj”, [say]: function () {console.log (“say”);} };  console.log (obj[name]);(//“lnj”)  obj[Symbol(“name”)] = “it666”;(//不会将原有的覆盖掉)”,使用for in循环是无法遍历一个对象symbol类型的属性/方法的,Object类对象调用它的getOwnPropertySymbols方法可以返回传入对象中symbol类型属性/方法名称所组成的数组,标准和规范就叫做接口,这里的接口和现实中的接口是一样的,例如USB接口就有它的标准和规范,所以A厂商生产的USB线可以插到B厂商电脑的USB接口上,Iterator叫做迭代器,即迭代程序,也是一种接口(即标准和规范),Iterator接口规定了不同数据类型的统一访问机制,此统一访问机制主要是指能被for of循环所遍历,默认情况下,Array、Map、Set、String、和TypedArray类的实例对象,以及函数的arguments对象和NodeList对象(DOM节点的集合)都实现了Iterator接口,也就是都能被for of循环所遍历,当一个数据(对象)能被for of循环所遍历时,此数据(对象)就一定有一个叫做[Symbol.iterator]的方法,此数据(对象)调用它的[Symbol.iterator]方法可以返回一个可迭代对象,例如“let arr = [1, 3, 5];  let it = arr[Symbol.iterator] ();(//变量it的值是一个可迭代对象)”,此可迭代对象调用它的next方法可以每次调用都返回一个拥有两个属性的对象,例如“{value: 1, done: false}”,value值是当前所遍历到的元素,done值是true/false,true代表遍历完毕,false代表还没有遍历完毕,所以,for of循环的内部实现原理就是不断地调用next方法,并把value值赋值给变量value,并判断是否遍历完毕,当遍历完毕时,就不再调用next方法了,只有实现了Iterator接口的数据(对象),才能够对其进行解构赋值和使用扩展运算符,Generator函数是ES6提供的一种异步编程解决方案,只需要在普通函数的function函数声明符后面加上*即可,在Generator函数作用域内可以使用yield操作符(只能在Generator函数中使用)封装多个状态,并且可以将代码块划分成多个部分,因此Generator函数又可以理解为是一个状态机,例如“function* gen () {console.log (“123”);  yield “aaa”;  console.log (“567”);  yield 1 + 1;}”,调用Generator函数后,此函数中所封装的代码不会立即执行,无论此函数有没有返回值,都会返回一个可迭代对象,此可迭代对象调用它的next方法可以每次调用都会执行此Generator函数作用域内yield操作符所划分的一部分代码,返回值是一个拥有两个属性的对象,value值是yield操作符所作用的值,done值是true/false(true代表已经结束了,不能再迭代了,false代表还未结束,还可以再迭代),在调用next方法的时候可以传入一个实参,此实参会作为上一个yield操作符的返回值,Generator函数的应用场景是可以让函数返回多个值,例如“function* calculate (a, b) {yield a + b;  yield a - b;}  let it = calculate (10, 5);  console.log (it.next ().value);  console.log (it.next ().value);”,可以在任意对象上快速部署Iterator接口,例如“let obj = {name: “lnj”, age: 34, gender: “man”};  function* gen () {let keys = Object.keys (obj);  for (let i = 0; i < keys.length; i++) {yield obj[keys[i] ];} }  obj[Symbol.iterator] = gen;  let it = obj[Symbol.iterator] ();  console.log (it.next () );”,可以实现用同步流程来表示异步操作,例如“function request () {return new Promise (function (resolve, reject) {setTimeout (function () {resolve (“获取到的数据”);}, 1000);} );}  function* gen () {yield request ();  yield request ();  yield request ();}  let it = gen ();  it.next ().value.then (function (data) {console.log (data, 1);  return it.next ().value;}).then (function (data) {console.log (data, 2);  return it.next ().value;}).then (function (data) {console.log (data, 3);} );”,async函数声明符是ES8中新增的一个声明符,用于定义一个异步函数(即解决异步问题的函数,可以使代码按顺序同步执行),跟普通函数的用法一样,当调用async函数时,其作用域中的代码会自动从上至下的执行,使用await操作符(只能在async函数中使用)可以暂停当前async函数的执行,当其所作用的Promise对象(即操作数)变为成功状态时,它的[[PromiseValue]]值会作为此await操作符的返回值,然后继续执行此async函数,当其所作用的Promise对象(即操作数)变为失败状态时,此web浏览器的控制台会throw一个错误和它的[[PromiseValue]]值,就不再继续执行此async函数了,当其所作用的操作数不是一个Promise对象,而仅仅是一个常量时(比如123),系统会把这个常量包装成Promise.resolve (xx),同理,当其没有操作数时,系统会把它的操作数包装成Promise.resolve (undefined),一个async函数无论最后return啥,当调用它的时候,返回的都是一个继承了此await操作符的操作数状态的Promise对象(不存在await操作符就返回成功状态的Promise对象),其[[PromiseValue]]值是此async函数return的值,在一个调用了async函数的函数作用域中,当想要让代码按顺序同步执行时,必须将此函数也变成async函数,并且在调用了async函数的位置await一下才好使(即双async await),例如“async function gen () {let res1 = await request ();  console.log (res1, 1);  let res2 = await request ();  console.log (res2, 2);  let res3 = await request ();  console.log (res3, 3);}  gen ();(//上面的Generator函数用同步流程来表示异步操作是这种写法的内部实现原理,这种写法可以看作是它的缩写)”

九、zepto.js类库

zepto.js是一个轻量级的针对现代高级浏览器的JS类库,是专门用于移动端的轻量级的jQuery.js,它与jQuery.js有着类似的api,当你会使用jQuery.js时,你就会使用zepto.js,由于jQuery.js更多的是用在PC端,所以jQuery.js考虑了很多低级浏览器的兼容性问题,代码更多,体积更大,并且做动画的内部实现原理是利用JS操作DOM元素,由于zepto.js更多的是用在移动端,所以zepto.js则是直接抛弃了低级浏览器的适配问题,代码更少,体积更小,并且做动画的内部实现原理是利用CSS3中相关的属性,zepto.js英文官方文档的网址是“zeptojs.com”,中文官方文档的网址是“www.css88.com/doc/zeptojs_api”,zepto.js采用了模块化的开发,将不同的功能放到了不同的模块(js文件)中,在使用的过程中可以按需引入,也就是需要什么功能就引入什么模块,从官方网站下载的zepto.js已经包含了一些默认的模块,从GitHub下载的zepto.js需要我们自己手动引入每一个模块,后续学习了NodeJS后,我们也可以自己定制,将不同的模块打包成一个模块,由于移动端的事件很多,例如单击、双击、轻扫、捏合、和拖拽等等,所以当我们在移动端使用click来监听点击事件时,系统需要花费100~300毫秒判断到底是什么事件,而移动端对事件响应速度的要求很高,事件响应越快用户体验就越好,所以当我们需要在移动端监听点击事件时,请使用tap事件,tap事件是zepto.js自己封装的一个事件,解决了原生click事件100~300毫秒的延迟问题,例如“$ (“div”).tap (function () {console.log (“被点击了”);} );”,给zepto的DOM元素集合所绑定的swipe/swipeLeft/swipeRight/swipeUp/swipeDown事件的触发条件是手指在此集合所包含的DOM元素上轻扫/向左/向右/向上/向下轻扫

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容