js新特性之网络编程
1.h5新增存储方案
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>18-H5新增存储方案</title> </head> <body> <button class="save">存点cookie</button> <button class="send">发送请求</button> <button class="btn1">保存</button> <button class="btn2">删除</button> <button class="btn3">修改</button> <button class="btn4">查找</button> <button class="btn5">清空</button> <script src="js/jquery-1.12.4.js"></script> <script src="myAjax2.js"></script> <script> /* 1.什么是SessionStorage和LocalStorage 和Cookie一样, SessionStorage和LocalStorage也是用于存储网页中的数据的 2.Cookie、 SessionStorage、LocalStorage区别 2.1生命周期(同一浏览器下) Cookie生命周期: 默认是关闭浏览器后失效, 但是也可以设置过期时间 SessionStorage生命周期: 仅在当前会话(窗口)下有效,关闭窗口或浏览器后被清除, 不能设置过期时间 LocalStorage生命周期: 除非被清除,否则永久保存 2.2容量 Cookie容量: 有大小(4KB左右)和个数(20~50)限制 SessionStorage容量: 有大小限制(5M左右) http://dev-test.nemikor.com/web-storage/support-test/ LocalStorage容量: 有大小限制(5M左右) http://dev-test.nemikor.com/web-storage/support-test/ 2.3网络请求 Cookie网络请求: 每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 SessionStorage网络请求: 仅在浏览器中保存,不参与和服务器的通信 LocalStorage网络请求: 仅在浏览器中保存,不参与和服务器的通信 3.Cookie、 SessionStorage、LocalStorage应用场景 Cookie: 判断用户是否登录 LocalStorage: 购物车 sessionStorage: 表单数据 4.注意点: 无论通过以上那种方式存储的数据, 切记不能将敏感数据直接存储到本地 */ $('.save').click(function () { document.cookie = "myName=it666;path=/;domain=127.0.0.1;"; }); $('.send').click(function () { ajax("18-cookie.php", {}, 3000, function (xhr) { console.log("请求成功", xhr.responseText); }, function () { console.log("请求失败"); }); }); //进行以下操作时localStorage和 sessionStorage一样 $('.btn1').click(function () { sessionStorage.setItem("name", "lnj"); // sessionStorage.setItem("age", "34"); //localStorage.setItem("name", "lnj"); }); $('.btn2').click(function () { sessionStorage.removeItem("name"); }); $('.btn3').click(function () { sessionStorage.setItem("name", "it666"); }); $('.btn4').click(function () { let value = sessionStorage.getItem("name"); alert(value); }); $('.btn5').click(function () { sessionStorage.clear(); }); </script> </body> </html>
2.同源策略
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>19-同源策略</title> <script src="js/jquery-1.12.4.js"></script> </head> <body> <button class="send">发送请求</button> <script> /* 1.什么是同源策略? 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能 所谓同源是指: 协议,域名,端口都相同,就是同源, 否则就是跨域 http://www.it666.com:80/index.html 协议: http/https/... 一级域名: it666.com/itzb.com 二级域名: www/study/edu/... 端口号: 80/3306/... // 协议+一级域名+二级域名+端口号都相同, 所以同源 http://www.it666.com:80/index.html http://www.it666.com:80/detail.html // 协议不同, 所以不同源, 是跨域 http://www.it666.com:80/index.html https://www.it666.com:80/index.html // 一级域名不同, 所以不同源, 是跨域 http://www.it666.com:80/index.html http://www.itzb.com:80/index.html // 二级域名不同, 所以不同源, 是跨域 http://www.it666.com:80/index.html http://edu.it666.com:80/index.html // 端口号不同, 所以不同源, 是跨域 http://www.it666.com:80/index.html http://www.it666.com:8090/index.html 2.同源策略带来的影响 在同源策略下, 浏览器只允许Ajax请求同源的数据, 不允许请求不同源的数据 但在企业开发中, 一般情况下为了提升网页的性能, 网页和数据都是单独存储在不同服务器上的 这时如果再通过Ajax请求数据就会拿不到跨域数据 3.跨域解决方案 jsonp document.domain+iframe location.hash + iframe window.name + iframe window.postMessage flash等第三方插件 * */ /* 当前的网页地址: http://127.0.0.1:80/jQuery/Ajax/19-%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5.html 请求的资源地址: http://127.0.0.1:80/jQuery/Ajax/19-SameOriginPolicy.php 当前的网页地址: http://127.0.0.1:63342/jQuery/Ajax/19-%E5%90%8C%E6%BA%90%E7%AD%96%E7%95%A5.html 请求的资源地址: http://127.0.0.1:80/jQuery/Ajax/19-SameOriginPolicy.php */ $('.send').click(function () { $.ajax({ url:"19-SameOriginPolicy.php", success: function (msg) { console.log(msg); }, error: function () { console.log("请求失败"); } }); }); </script> </body> </html>
-
后端
<?php echo 'it666.com' ?>
3.jsonp原理
<button>我是按钮</button> <script> /* 1.什么是JSONP? JSONP让网页从别的地址(跨域的地址)那获取资料,即跨域读取数据 2.JSONP实现跨域访问的原理 2.1在同一界面中可以定义多个script标签 2.2同一个界面中多个script标签中的数据可以相互访问 2.3可以通过script的src属性导入其它资源 2.4通过src属性导入其它资源的本质就是将资源拷贝到script标签中 2.5script的src属性不仅能导入本地资源, 还能导入远程资源 2.6由于script的src属性没有同源限制, 所以可以通过script的src属性来请求跨域数据 */ // let num = 666; function demo() { console.log("demo"); } </script> <!--以下就是将20-jsonp.js里面的内容拷贝进去--> <script src="20-jsonp.js"> // let num = 777; // function test() { // console.log("test777"); // } </script> <script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php"></script> <script> // console.log(num); // test(); // $("button").click(function () { // alert("按钮被点击了"); // }); /* 当前网页的地址: http://127.0.0.1:63342/jQuery/Ajax/20-jsonp%E5%8E%9F%E7%90%86.html 远程资源的地址: http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php */ console.log(num); </script>
-
后端
<?php echo "let num = 789;"; echo "demo(666);"; ?>
4.jsonp优化
<!--<script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test"></script>--> <script> /* 优化一 1.在企业开发中通过JSONP来获取跨域的数据, 一般情况下服务器返回的都不会是一个变量, 而是一个函数的调用 */ /* 优化二 2.当前服务器返回的函数调用名称写死了 服务器返回函数叫什么名称, 我们本地就必须定义一个叫什么名称的函数 */ /* 解决方案: 通过URL参数的方式来动态指定函数名称 在地址后边加个?cb=test" */ /* 优化三 3.由于script标签默认是同步, 前面的script标签没有加载完数据, 后面的script标签就不会被执行 所以请求数据的script标签必须放到后面 */ /* 解决方案: 通过JS动态创建script标签, 因为JS动态创建的script标签默认就是异步的, 不用等到前面的标签加载完就可以执行后面的script标签 */ //下为优化3 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); } </script> <!-- 下为优化2 <script src="http://127.0.0.1:80/jQuery/Ajax/20-jsonp.php?cb=test"> // demo(666); // test(666); </script> -->
-
后端
<?php $cb = $_GET['cb']; // test echo $cb."(666);"; // test(666); ?>
5.jQuery中的jsonp
<script src="js/jquery-1.12.4.js"></script> <script> /* 当前网页的地址: http://127.0.0.1:63342/jQuery/Ajax/22-jQuery.html 当前资源的地址: http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php */ $.ajax({ url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php", data:{ "teacher": "lnj", "age": 34 }, dataType: "jsonp", // 告诉jQuery需要请求跨域的数据 jsonp: "cb", // 告诉jQuery服务器在获取回调函数名称的时候需要用什么key来获取 jsonpCallback: "lnj", // 告诉jQuery服务器在获取回调函数名称的时候回调函数的名称是什么 //需要注意的是jQuery中的jsonp不需要定义函数,会自己将回调函数中的 参数返回给msg success: function (msg) { console.log(msg); } }); </script>
-
后端
<?php // 0.拿到传递过来的数据 $teacher = $_GET["teacher"]; $age = $_GET["age"]; $arr = array("name"=>$teacher, "age"=>$age); $data = json_encode($arr); // 1.拿到回调函数的名称 //$cb = $_GET["callback"]; // jQuery112406520384710124194_1559732574283 $cb = $_GET["cb"]; // lnj // 2.返回数据 //echo $cb."(666);"; // jQuery112406520384710124194_1559732574283(666); echo $cb."(".$data.");"; // lnj(666); ?>
6.jsonp封装(自己实现一个jsonp)
function obj2str(obj) { // 生成随机因子 obj.t = (Math.random() + "").replace(".", ""); let arr = []; for(let key in obj){ //encodeURI用于将中文转换为什么编码 arr.push(key + "=" + encodeURI(obj[key])); } let str = arr.join("&"); // console.log(str); return str; } function myJSONP(options) { options = options || {}; // http://127.0.0.1/jQuery/Ajax/22-jsonp.php?cb=lnj&teacher=lnj&age=34&_=1559735634387 // http://127.0.0.1/jQuery/Ajax/22-jsonp.php?cb=lnj&teacher=lnj&age=34&t=08520581619221432 // 1.生成URL地址 let url = options.url; if(options.jsonp){ url += "?" + options.jsonp + "="; }else{ url += "?callback="; } let callbackName = ("jQuery" + Math.random()).replace(".", ""); if(options.jsonpCallback){ callbackName = options.jsonpCallback; url += options.jsonpCallback; }else{ // console.log(callbackName); url += callbackName; } if(options.data){ let str = obj2str(options.data); url += "&" + str; } // console.log(url); // 2.获取跨域的数据 let oScript = document.createElement("script"); oScript.src = url; document.body.appendChild(oScript); // 3.定义回调函数 window[callbackName] = function (data) { // 删除已经获取了数据的script标签 document.body.removeChild(oScript); // 将获取到的数据返回给外界 options.success(data); } }
-
html调用
myJSONP({ url: "http://127.0.0.1:80/jQuery/Ajax/22-jsonp.php", data:{ "teacher": "lnj", "age": 34 }, jsonp: "cb", // 告诉jQuery服务器在获取回调函数名称的时候需要用什么key来获取 jsonpCallback: "lnj", // 告诉jQuery服务器在获取回调函数名称的时候回调函数的名 称是什么 success: function (msg) { console.log(msg); } });
7.....
- 了解静态数据和动态数据
- 了解程序进程和线程之间的关系
- 了解串行和并行
8.js串行和事件循环
<script> /* 1.JS是单线程的 所以JS中的代码都是串行的, 前面没有执行完毕后面不能执行 */ /* 2.同步代码和异步代码 除了"事件绑定的函数"和"回调函数"以外的都是同步代码 2.1程序运行会从上至下依次执行所有的同步代码 2.2在执行的过程中如果遇到异步代码会将异步代码放到事件循环中 2.3当所有同步代码都执行完毕后, JS会不断检测 事件循环中的异步代码是否满足条件 2.4一旦满足条件就执行满足条件的异步代码 (就如下边写的那个模拟代码) * */ /* 2.为什么JS是单线程的? avaScript的单线程,与它的用途有关。 作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。 这决定了它只能是单线程,否则会带来很复杂的同步问题。 例如: 如果JS是多线程的 现在有一个线程要修改元素中的内容, 一个线程要删除该元素, 这时浏览器应该以哪个线程为准? */ console.log("1"); // 同步代码 setTimeout(function () { // 异步代码 console.log("2"); }, 500); console.log("3"); // 同步代码 alert("666"); // 同步代码 // 1 / 3 / 2 //先执行同步代码,输出1 3 弹出666 然后将异步代码添加到一个数组中,这时如果不将666关闭,那么就说明 那个同步代码没有执行完毕,就不会输出2,这也证明了js是单线程的 /* // 系统添加代码模拟 let arr = [setTimeout(function () { // 异步代码 console.log("2"); }, 500)]; 事件循环 let index = 0; let length = arr.length; while(true){ let item = arr[index]; if(item.time === 500){ 执行异步代码 } index++; if(index === length){ index = 0; } } 扩展阅读: https://segmentfault.com/a/1190000015042127 */ </script>
9.promise
9.1 promise基本概念
<script> /* 1.什么是promise? promise是ES6中新增的异步编程解决方案, 在代码中的表现是一个对象 */ // 需求: 从网络上加载3个资源, 要求加载完资源1才能加载资源2, 加载完资源2才能加载资源3 // 前面任何一个资源加载失败, 后续资源都不加载 /* 我们用定时器模拟一下上面的需求 function request(fn) { setTimeout(function () { fn("拿到的数据"); }, 1000); } request(function (data) { console.log(data, 1); request(function (data) { console.log(data, 2); request(function (data) { console.log(data, 3); }); }); }); */ /* 2.promise作用 企业开发中为了保存异步代码的执行顺序, 那么就会出现回调函数层层嵌套 如果回调函数嵌套的层数太多, 就会导致代码的阅读性, 可维护性大大降低 promise对象可以将异步操作以同步流程来表示, 避免了回调函数层层嵌套(回调地狱) * */ function request() { return new Promise(function (resolve, reject) { setTimeout(function () { resolve("拿到的数据"); }, 1000); }); } request().then(function (data) { console.log(data, 1); return request(); }).then(function (data) { console.log(data, 2); return request(); }).then(function (data) { console.log(data, 3); }); </script>
9.2promise基本使用
<script> /* 1.什么是Promise? Promise是ES6中新增的一个对象, 通过Promise就可以实现 用同步的流程来表示异步的操作 通过Promise就可以 避免回调函数层层嵌套(回调地狱)问题 2.如何创建Promise对象? new Promise(function(resolve, reject){}); promise对象不是异步的, 只要创建promise对象就会立即执行存放的代码 3.Promise是如何实现 通过同步的流程来表示异步的操作的? promise对象是通过状态的改变来实现的, 只要状态发生改变就会自动触发对应的函数 如下所说,当通过在promise中调用函数,转为不同的状态,在外边通过状态的不同会调用不同的函数. 4.Promise对象三种状态 pending: 默认状态,只要没有告诉promise任务是成功还是失败就是pending状态 fulfilled(resolved): 只要调用resolve函数, 状态就会变为fulfilled, 表示操作成功 rejected: 只要调用rejected函数, 状态就会变为rejected, 表示操作失败 注意点: 状态一旦改变既不可逆, 既从pending变为fulfilled, 那么永远都是fulfilled 既从pending变为rejected, 那么永远都是rejected 5.监听Promise状态改变 我们还可以通过函数来监听状态的变化 resolved --> then() rejected --> catch() */ // console.log("1"); let promise = new Promise(function (resolve, reject) { console.log("2");//会立即输出 对应上面2 reject();//会调用catch()函数 对应345 // resolve(); }); // console.log(promise); promise.then(function () { console.log("then"); }); promise.catch(function () { console.log("catch"); }); </script>
9.3 then方法
<script> /* 0.then方法 then方法接收两个参数, 第一个参数是状态切换为成功时的回调, 第二个参数是状态切换为失败时的回调 * */ //以下会打印成功 let promise = new Promise(function (resolve, reject) { // resolve(); // 将状态修改为成功 reject(); // 将状态修改为失败 }); promise.then(function () { console.log("成功"); }, function () { console.log("失败"); }); /* 1.then方法 在修改promise状态时, 可以传递参数给then方法中的回调函数 */ // resolve = success, reject = error; //以下会输出失败aaa let promise = new Promise(function (resolve, reject) { // resolve("111"); // 将状态修改为成功 success("111"); reject("aaa"); // 将状态修改为失败 error("aaa"); }); promise.then(function (data) { console.log("成功", data); }, function (data) { console.log("失败", data); }); //原理如下 function success(data) { console.log(data); } function error(data) { console.log(data); } promise.then(success, error); /* 2.then方法 同一个promise对象可以多次调用then方法, 当该promise对象的状态变化时所有then方法都会被执行 */ //以下会输出 失败1 失败2 let promise = new Promise(function (resolve, reject) { // resolve(); // 将状态修改为成功 reject(); // 将状态修改为失败 }); promise.then(function () { console.log("成功1"); }, function () { console.log("失败1"); }); promise.then(function () { console.log("成功2"); }, function () { console.log("失败2"); }); /* 3.then方法 then方法每次执行完毕后会返回一个新的promise对象 */ //以下 p2是一个promise对象 但是promise === p2)为false let promise = new Promise(function (resolve, reject) { resolve(); // 将状态修改为成功 // reject(); // 将状态修改为失败 }); let p2 = promise.then(function () { console.log("成功1"); }, function () { console.log("失败1"); }); console.log(p2); console.log(promise === p2); /* 4.then方法 可以通过上一个promise对象的then方法给下一个promise对象的then方法传递参数 注意点: 无论是在上一个promise对象成功的回调还是失败的回调传递的参数, 都会传递给下一个promise对象成功的回调 */ //以下会输出 失败1 aaa 成功2 bbb let promise = new Promise(function (resolve, reject) { // resolve("111"); // 将状态修改为成功 reject("aaa"); // 将状态修改为失败 }); let p2 = promise.then(function (data) { console.log("成功1", data); return "222"; }, function (data) { console.log("失败1", data); return "bbb"; }); p2.then(function (data) { console.log("成功2", data); }, function (data) { console.log("失败2", data); }); /* 5.then方法 如果then方法返回的是一个Promise对象, 那么会将返回的Promise对象的 执行结果中的值传递给下一个then方法 */ //以下输出 成功1 111 失败2 bbb let promise = new Promise(function (resolve, reject) { resolve("111"); // 将状态修改为成功 // reject("aaa"); // 将状态修改为失败 }); let ppp = new Promise(function (resolve, reject) { // resolve("222"); // 将状态修改为成功 reject("bbb"); // 将状态修改为失败 }); let p2 = promise.then(function (data) { console.log("成功1", data); return ppp; }, function (data) { console.log("失败1", data); return "bbb"; }); p2.then(function (data) { console.log("成功2", data); }, function (data) { console.log("失败2", data); }); </script>
9.4 catch方法
<script> /* 0.catch方法 catch 其实是 then(undefined, () => {}) 的语法糖,就是后边的能传递参数 */ let promise = new Promise(function (resolve, reject) { // resolve(); // 将状态修改为成功,catch方法找不到的 reject(); // 将状态修改为失败 }); promise.catch(function () { console.log("abc"); }); /* 2.catch方法 注意点: 如果需要分开监听, 也就是通过then监听成功通过catch监听失败 那么必须使用链式编程, 否则会报错 */ let promise = new Promise(function (resolve, reject) { // resolve(); // 将状态修改为成功 reject(); // 将状态修改为失败 }); promise.then(function () { console.log("成功"); }).catch(function () { console.log("失败"); }); /* 以下会报错 promise.then(function () { console.log("成功"); }); promise.catch(function () { console.log("失败"); }); */ /* 了解一下报错的原因 3.catch方法 不使用链式编程报错的原因是 1.如果promise的状态是失败, 但是没有对应失败的监听就会报错 2.then方法会返回一个新的promise, 新的promise会继承原有promise的状态 3.如果新的promise状态是失败, 但是没有对应失败的监听也会报错 也就是说下边的p2是then方法返回的promise,而且promise的状态是失败,但是没有监听p2,所以会报错 */ let promise = new Promise(function (resolve, reject) { // resolve(); // 将状态修改为成功 reject(); // 将状态修改为失败 }); let p2 = promise.then(function () { console.log("成功"); }); console.log(p2); promise.catch(function () { console.log("失败1"); }); p2.catch(function () { console.log("失败2"); }); /* 与then方法的不同 .catch方法 和then方法第二个参数的区别在于, catch方法可以捕获上一个promise对象then方法中的异常 */ let promise = new Promise(function (resolve, reject) { resolve(); }); promise.then(function () { console.log("成功"); xxx }).catch(function (e) { console.log("失败", e);//会打印错误信息 }); </script>
9.5 异常处理
<script> /* 1.JS中的异常 简单粗暴就是有错误出现 由于JS是单线程的, 编写的代码都是串行的, 所以一旦前面代码出现错误,程序就会被中断, 后续代码就不会被执行 2.JS中的异常处理 2.1自身编写代码问题, --> 手动修复BUG 2.2外界原因问题, --> try{}catch{} 对于一些可预见的异常, 我们可以使用try{}catch{}来处理, 3.JS中如何进行异常处理 利用try{}catch{}来处理异常可以保证程序不被中断, 也可以记录错误原因以便于后续优化迭代更新 try { 可能遇到的意外的代码 } catch(e) { 捕获错误的代码块 } */ // function say(){ // console.log("say"); // } console.log("1"); try {//这样就算没有定义say函数也会继续执行代码 say(); }catch (e) { console.log(e); } console.log("2"); </script>
9.6 promise练习
<script> /* 需求: 一次加载一张图片添加到body中. 前面图片加载失败后面图片不加载 */ let arr = [ "http://www.it666.com/files/system/block_picture_1555415767.png", "http://www.it666.com/files/system/block_picture_1555422597.jpg", "http://wwww.it666.com/files/system/block_picture_1555419713.jpg" ]; function loadImage(url) { return new Promise(function (resolve, reject) { let oImg = new Image(); oImg.src = url; oImg.onload = function () { resolve(oImg); } oImg.onerror = function () { reject("图片加载失败"); } }); } loadImage(arr[0]).then(function (oImg) { // console.log(oImg); console.log("1"); document.body.appendChild(oImg); return loadImage(arr[1]); }).then(function (oImg) { console.log("2"); // console.log(oImg); document.body.appendChild(oImg); return loadImage(arr[2]); }).then(function (oImg) { console.log("3"); // console.log(oImg); document.body.appendChild(oImg); }).catch(function (msg) { console.log(msg); }); </script>
9.7 promise-all方法
<script> /* 需求: 1.无序加载图片, 每加载成功一张就添加一张 2.无序加载图片, 只有所有图片都加载成功才添加, 有一张图片失败都不添加 */ //1实现 let arr = [ "http://www.it666.com/files/system/block_picture_1555415767.png", "http://www.it666.com/files/system/block_picture_1555422597.jpg", "http://www.it666.com/files/system/block_picture_1555419713.jpg" ]; function loadImage(url) { return new Promise(function (resolve, reject) { let oImg = new Image(); let time = Math.random() * 1000; // console.log(time); setTimeout(function () { oImg.src = url; }, time); // oImg.src = url; oImg.onload = function () { resolve(oImg); } oImg.onerror = function () { reject("图片加载失败了"); } }); } /* Promise的all静态方法: 1.all方法接收一个数组, 2.如果数组中有多个Promise对象,只有都成功才会执行then方法, 并且会按照添加的顺序, 将所有成功的结果重新打包到一个数组中返回给我们 3.如果数组中不是Promise对象, 那么会直接执行then方法 应用场景: 批量加载, 要么一起成功, 要么一起失败 * */ /* let p1 = new Promise(function (resolve, reject) { // resolve("111"); reject("aaa"); }); let p2 = new Promise(function (resolve, reject) { setTimeout(function () { resolve("222"); }, 5000); }); let p3 = new Promise(function (resolve, reject) { setTimeout(function () { resolve("333"); }, 3000); }); Promise.all([p1, p2, p3]).then(function (result) { console.log("成功", result); }, function (err) { console.log("失败", err); }); */ //2实现 Promise.all([loadImage(arr[0]), loadImage(arr[1]),loadImage(arr[2])]) .then(function (result) { // console.log(result); result.forEach(function (oImg) { document.body.appendChild(oImg); }); }) .catch(function (e) { console.log(e); }); </script>
10.fetch网络请求
<script> /* 1.什么是fetch? 和Ajax一样都是用于请求网络数据的 fetch是ES6中新增的, 基于Promise的网络请求方法 2.fetch基本使用 fetch(url, {options}) .then() .catch(); http://127.0.0.1/jQuery/Ajax/41.php */ /* fetch("http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34", { //get请求如果发送数据直接写在url后边 method: "get" }).then(function (res) { // console.log(res.text()); // return res.text(); return res.json();//可以将返回的数据转换成一个json对象 }).then(function (data) { console.log(data); console.log(typeof data); }).catch(function (e) { console.log(e); }); */ fetch("http://127.0.0.1/jQuery/Ajax/41.php", { method: "post", body: JSON.stringify({teacher:"zq", age:666}) //post传参如上 }).then(function (res) { // console.log(res.text()); // return res.text(); return res.json(); }).then(function (data) { console.log(data); console.log(typeof data); }).catch(function (e) { console.log(e); }); </script>
11.axios插件的使用
<script src="js/axios.js"></script> <script> /* 1.什么是axios? Axios 是一个基于 promise 的 HTTP 库网络请求插件 2.axios特点 2.1可以用在浏览器和 node.js 中 2.2支持 Promise API 2.3自动转换 JSON 数据 2.4客户端支持防御 XSRF */ // axios.get("http://127.0.0.1/jQuery/Ajax/41.php") // axios.get("http://127.0.0.1/jQuery/Ajax/41.php?teacher=lnj&age=34") axios.post("http://127.0.0.1/jQuery/Ajax/41.php", { teacher: "lnj", age: 666 }) .then(function (res) { console.log(res.data); }) .catch(function (e) { console.log(e); }); /* 3.全局的 axios 默认值 在企业开发中项目分为 :开发阶段和部署阶段, 这两个阶段项目存储的位置是不同的 项目上线前存储在企业内部测试服务器上, 项目上线后存储在企业正式服务器上 所以如果每次请求都将请求的地址写在请求中, 那么项目上线时需要大量修改请求地址 为了解决这个问题, 我们可以配置一个全局URL根地址, 项目上线时只需要修改根地址即可 例如: 上线前地址是: http://127.0.0.1/jQuery/Ajax/41.php 上线后地址是: http://192.199.13.14/jQuery/Ajax/41.php */ axios.defaults.timeout = 2000; axios.defaults.baseURL = "http://127.0.0.1"; axios.post("/jQuery/Ajax/41.php", { teacher: "lnj", age: 666 }) .then(function (res) { console.log(res.data); }) .catch(function (e) { console.log(e); }); </script>
12.Symbol
12.1 Symbol基本概念
<script> /* 1.什么Symbol? Symbol是ES6中新增的一种数据类型, 被划分到了基本数据类型中 基本数据类型: 字符串、数值、布尔、undefined、null、Symbol 引用数据类型: Object 2.Symbol的作用 用来表示一个独一无二的值 3.如果生成一个独一无二的值? let xxx = Symbol(); */ /* 4.为什么需要Symbol? 在企业开发中如果需要对一些第三方的插件、框架进行自定义的时候 可能会因为添加了同名的属性或者方法, 将框架中原有的属性或者方法覆盖掉 为了避免这种情况的发生, 框架的作者或者我们就可以使用Symbol作为属性或者方法的名称 5.如何区分Symbol? 在通过Symbol生成独一无二的值时可以设置一个标记如 Symbol("name"); 这个标记仅仅用于区分, 没有其它任何含义 */ // let xxx = Symbol(); // let yyy = Symbol(); // console.log(xxx === yyy); /* let obj = { name: "lnj", say: function () { console.log("say"); } } obj.name = "it666"; console.log(obj.name); obj.say = function () { console.log("test"); } obj.say(); */ let name = Symbol("name"); let say = Symbol("say"); let obj = { // 注意点: 如果想使用变量作为对象属性的名称, 那么必须加上[] [name]: "lnj", [say]: function () { console.log("say"); } } // obj.name = "it666"; obj[Symbol("name")] = "it666"; //不会覆盖框架里定义的 console.log(obj); </script>
12.2 Symbol注意点
<script> // 1.通过Symbol生成独一无二值时需要在后面加上(), 但是前面不能加new, 因为它不是引用类型 let xxx = Symbol(); // 正确 let xxx = new Symbol(); // 错误 // 2.通过Symbol生成独一无二值时传入的字符串仅仅是一个标记, 方便我们阅读代码, 没有其它任何意义 // let xxx = Symbol("name"); // 3.做类型转换的时候不能转换成数值 let xxx = Symbol("name"); console.log(String(xxx)); console.log(Boolean(xxx)); console.log(Number(xxx));//报错 // 4.不能做任何运算 let xxx = Symbol("name"); console.log(xxx + "abc"); console.log(xxx + 123); // 5.Symbol生成的值作为属性或方法名称时, 一定更要保存下来, 否则后续无法使用 // let name = Symbol("name"); let obj = { // [name]: "lnj" [Symbol("name")]: "it666" } //console.log(obj[name]); console.log(obj[Symbol("name")]);//拿不到,有创建了一个新的独一无二的值 // 6.for循环无法遍历出Symbol的属性和方法 let name = Symbol("name"); let say = Symbol("say"); let obj = { // 注意点: 如果想使用变量作为对象属性的名称, 那么必须加上[] [name]: "lnj", [say]: function () { console.log("say"); }, age: 34, gender: "man", hi: function () { console.log("hi"); } } for(let key in obj){ console.log(key); } //通过下面这个方法来获取symbol属性 ,会返回一个数组 console.log(Object.getOwnPropertySymbols(obj)); </script>
13.Iterator
13.1 基本概念
<script> /* 1.什么是Iterator? Iterator又叫做迭代器, 是一种接口 这里的接口和现实中接口一样, 是一种标准一种规范 例如: 电脑的USB接口有电脑USB接口的标准和规范, 正式因为有了标准和规范 所以A厂商生成的USB线可以插到B厂商电脑的USB接口上 它规定了不同数据类型统一访问的机制, 这里的访问机制主要指数据的遍历 在ES6中Iterator接口主要供for...of消费 2.默认情况下以下数据类型都实现的Iterator接口 Array/Map/Set/String/TypedArray/函数的 arguments 对象/NodeList 对象 */ /* 1.只要一个数据已经实现了Iterator接口, 那么这个数据就有一个叫做[Symbol.iterator]的属性 2.[Symbol.iterator]的属性会返回一个函数 3.[Symbol.iterator]返回的函数执行之后会返回一个对象 4.[Symbol.iterator]函数返回的对象中又一个名称叫做next的方法 5.next方法每次执行都会返回一个对象{value: 1, done: false}done为false说明还没有执行完 6.这个对象中存储了当前取出的数据和是否取完了的标记 */ let arr = [1, 3, 5]; console.log(arr[Symbol.iterator]); let it = arr[Symbol.iterator](); console.log(it); console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next()); for(let value of arr){ console.log(value); } //对象没有实现,所以以下会报错 // let obj = { // name: "lnj", // age: 34, // gender: "man" // } // console.log(obj[Symbol.iterator]); // for(let value of obj){ // console.log(value); // } //以下我们自己实现Iterator,是的一个对象也可以通过for...of消费 class MyArray{ constructor(){ for(let i = 0; i < arguments.length; i++){ // this[0] = 1; // this[1] = 3; // this[2] = 5; this[i] = arguments[i]; } this.length = arguments.length; } [Symbol.iterator](){//和以前在类里面写的函数格式不一样 let index = 0; let that = this; return { next(){ if(index < that.length){ return {value: that[index++], done: false} }else{ return {value: that[index], done: true} } } } } } let arr = new MyArray(1, 3, 5); // console.log(arr); // console.log(arr[0]); // arr[0] = 666; // console.log(arr); for(let value of arr){ console.log(value); } // console.log(arr[Symbol.iterator]); // let it = arr[Symbol.iterator](); // console.log(it); // console.log(it.next()); // console.log(it.next()); // console.log(it.next()); // console.log(it.next()); </script>
13.2 应用场景
<script> // 1.解构赋值 class MyArray{ constructor(){ for(let i = 0; i < arguments.length; i++){ // this[0] = 1; // this[1] = 3; // this[2] = 5; this[i] = arguments[i]; } this.length = arguments.length; } [Symbol.iterator](){ let index = 0; let that = this; return { next(){ if(index < that.length){ return {value: that[index++], done: false} }else{ return {value: that[index], done: true} } } } } } // let arr = [1, 3]; let arr = new MyArray(1, 3); let [x, y, z] = arr;//将next中的value给x,y,没有就undefined console.log(x, y, z); // 2.扩展运算符 // let arr1 = [1, 3]; // let arr2 = [2, 4]; let arr1 = new MyArray(1, 3); let arr2 = new MyArray(2, 4); let arr3 = [...arr1, ...arr2]; console.log(arr3); //通过上面的例子,如果我们想要使用扩展运算符等,就可以自定义iterator接口来实现 </script>
14 Generator函数
14.1 基本概念和使用
<script> /* 1.什么是Generator函数? Generator 函数是 ES6 提供的一种异步编程解决方案 Generator 函数内部可以封装多个状态, 因此又可以理解为是一个状态机 2.如何定义Generator函数 只需要在普通函数的function后面加上*即可 3.Generator函数和普通函数区别 3.1调用Generator函数后, 无论函数有没有返回值, 都会返回一个迭代器对象, 3.2调用Generator函数后, 函数中封装的代码不会立即被执行 4.真正让Generator具有价值的是yield关键字 4.1在Generator函数内部使用yield关键字定义状态 4.2并且yield关键字可以让 Generator内部的逻辑能够切割成多个部分。 4.3通过调用迭代器对象的next方法执行一个部分代码,调用一次就执行第一部分的内容,两次就执行二部分 执行哪个部分就会返回哪个部分定义的状态 5.在调用next方法的时候可以传递一个参数, 这个参数会传递给上一个yield */ function* gen() { console.log("123"); //1部分 let res = yield "aaa"; console.log(res);//2部分 console.log("567"); yield 1 + 1; console.log("789");//3部分 yield true; } let it = gen(); // console.log(it); console.log(it.next()); console.log(it.next("it666"));//这个参数传给了上一个yield,会输出it666 567 以及这部分的状 态 console.log(it.next()); console.log(it.next());//没有这个状态,输出undefined // 注意点: yield关键字只能在Generator函数中使用, 不能在普通函数中使用 // function say() { // yield "abc"; // } // say(); </script
14.2 应用场景
<script> /* 应用场景, 让函数返回多个值 */ /* function calculate(a, b) { let sum = a + b; let sub = a - b; return [sum, sub]; } */ 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); </script>
<script> /* 1. 应用场景: 利用 Generator 函数,可以在任意对象上快速部署 Iterator 接口 */ /* Generator 函数特点 1.Generator 函数也是一个函数 2.Generator 函数会返回一个迭代器对象 3.迭代器对象有next方法 4.next方法每次执行都会返回一个对象{value: xxx, done: false} */ /* function* gen() { yield "aaa"; yield "bbb"; yield "ccc"; } let it = gen(); // console.log(it); console.log(it.next()); */ /* 1.必须有一个叫做[Symbol.iterator]的属性 2.[Symbol.iterator]的属性会返回一个函数 3.[Symbol.iterator]返回的函数执行之后会返回一个可迭代对象 4.[Symbol.iterator]函数返回的对象中又一个名称叫做next的方法 5.next方法每次执行都会返回一个对象{value: xxx, done: false} */ /* let obj = { name: "lnj", age: 34, gender: "man", [Symbol.iterator](){ let keys = Object.keys(this); // console.log(keys); let index = 0; let that = this; return { next(){ if(index < keys.length){ return {value: that[keys[index++]], done: false}; }else{ return {value: undefined, done: true}; } } } } } // console.log(obj[Symbol.iterator]);返回函数 // let it = obj[Symbol.iterator]();返回可迭代对象 // console.log(it); // console.log(it.next()); // console.log(it.next()); // console.log(it.next()); // console.log(it.next()); for(let value of obj){ console.log(value); } */ 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; // console.log(obj[Symbol.iterator]); let it = obj[Symbol.iterator](); // console.log(it); console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next()); </script>
<script> /* 应用场景: 用同步的流程来表示异步的操作 */ /* function request(fn) { setTimeout(function () { fn("拿到的数据"); }, 1000); } request(function (data) { console.log("1", data); request(function (data) { console.log("2", data); request(function (data) { console.log("3", data); }); }); }); */ function request() { return new Promise(function (resolve, reject) { setTimeout(function () { resolve("拿到的数据"); }, 1000); }); } /* request().then(function (data) { console.log(data, 1); return request(); }).then(function (data) { console.log(data, 2); return request(); }).then(function (data) { console.log(data, 3); }); */ function* gen() { yield request(); yield request(); yield request(); } let it = gen(); // console.log(it.next().value);//返回的promise对象放在value里面 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); }); </script>
14.3 async函数
<script> //我们上面通过Generator函数来用同步流程表示异步操作,但是看起来很麻烦,async函数就是来解决那个问 题的 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 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(); /* 1.async函数 async函数是ES8中新增的一个函数, 用于定义一个异步函数 async函数函数中的代码会自动从上至下的执行代码 2.await操作符 await操作符只能在异步函数 async function 中使用 await表达式会暂停当前 async function 的执行,等待 Promise 处理完成。 若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,然后继续执行 async function。 * */ </script>
网友评论