大家好,我来了!本期为大家带来的Web前端学习知识是”Web前端:ES6是干什么的?(下)“,喜欢Web前端的小伙伴,一起看看吧!

主要内容

  1. Promise
  2. Generator
  3. Async
  4. Class
  5. Extends
  6. proxy

学习目标

第一节 Promise

1.1 promise是什么?

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

1.2 promsie产生的原因

在JavaScript的世界中,所有代码都是单线程执行的。

由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现:

function callback() {console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒钟后调用callback函数
console.log('after setTimeout()');

观察上述代码执行,在Chrome的控制台输出可以看到:

before setTimeout()
after setTimeout()
(等待1秒后)
Done

可见,异步操作会在将来的某个时间点触发一个函数调用。

异步回调的问题:

  • 之前处理异步是通过纯粹的回调函数的形式进行处理
  • 很容易进入到回调地狱中,剥夺了函数return的能力
  • 问题可以解决,但是难以读懂,维护困难
  • 稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护

回调地狱

一般情况我们一次性调用API就可以完成请求。
有些情况需要多次调用服务器API,就会形成一个链式调用,比如为了完成一个功能,我们需要调用API1、API2、API3,依次按照顺序进行调用,这个时候就会出现回调地狱的问题

1.3 promise详解

1.3.1 语法

new Promise(function (resolve, reject) {// 一段耗时的异步操作resolve('成功') // 数据处理完成// reject('失败') // 数据处理出错}).then((res) => {console.log(res)},  // 成功(err) => {console.log(err)} // 失败)

resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

【代码演示】

请求网络接口:

图片懒加载

1.3.2 promise有三个状态:

1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。

Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了。

1.4 promise案例

回调包装成Promise,他有两个显而易见的好处:
1、可读性好
2、返回 的结果可以加入任何Promise队列

实战示例,回调地狱和promise对比:

1.4.1 传统写法

/***第一步:找到北京的id第二步:根据北京的id -> 找到北京公司的id第三步:根据北京公司的id -> 找到北京公司的详情目的:模拟链式调用、回调地狱***/// 回调地狱// 请求第一个API: 地址在北京的公司的id$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success (resCity) {let findCityId = resCity.filter(item => {if (item.id == 'c1') {return item}})[0].id$.ajax({//  请求第二个API: 根据上一个返回的在北京公司的id “findCityId”,找到北京公司的
第一家公司的idurl: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success (resPosition) {let findPostionId = resPosition.filter(item => {if(item.cityId == findCityId) {return item}})[0].id// 请求第三个API: 根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success (resCom) {let comInfo = resCom.filter(item => {if (findPostionId == item.id) {return item}})[0]console.log(comInfo)}})}})}})

1.4.2 Promise

onst cityList = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success (res) {resolve(res)}})})// 第二步:找到城市是北京的idcityList.then(res => {let findCityId = res.filter(item => {if (item.id == 'c1') {return item}})[0].idfindCompanyId().then(res => {// 第三步(2):根据北京的id -> 找到北京公司的idlet findPostionId = res.filter(item => {if(item.cityId == findCityId) {return item}})[0].id// 第四步(2):传入公司的idcompanyInfo(findPostionId)})})// 第三步(1):根据北京的id -> 找到北京公司的idfunction findCompanyId () {let aaa = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success (res) {resolve(res)}})})return aaa}// 第四步:根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情function companyInfo (id) {let companyList = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success (res) {let comInfo = res.filter(item => {if (id == item.id) {return item}})[0]console.log(comInfo)}})})}

本章作业

Promise是什么 如何使用

第二节Generator

Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同

2.1 Generator语法

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。

function* getData() {yield http();yield getLog();
}// Generator函数function* generator() {yield 'status one'         // yield 表达式是暂停执行的标记  return 'hello world'}let iterator = generator()   // 调用 Generator函数,函数并没有执行,返回的是一个Iterator对象iterator.next()              // {value: "status one", done: false},value 表示返回值,
done 表示遍历还没有结束iterator.next()              // {value: "hello world", done: true},value 表示返回值,
done 表示遍历结束

yield 表达式

由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。

遍历器对象的next方法的运行逻辑如下。

(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。

(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。

(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。

function* getData() {yield http();yield getLog();
}
function getLog() {console.log("我是网络请求");
}
function http() {return $.ajax({type: "get",url: "http://iwenwiki.com/api/blueberrypai/getIndexChating.php",success: function (data) {console.log(data);}})
}var gd = getData();
gd.next();
gd.next();

2.2 async

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

async 函数是什么?一句话,它就是 Generator 函数的语法糖

function getLog(result,ms) {console.log(result);// 页面渲染函数$("#root").append(`<img src='${ result.titleImg }' />`);return new Promise((resolve) => {setTimeout(resolve, ms);});
}function Hello() {console.log("我是最后执行");
}function http() {return $.ajax({type: "get",url: "http://iwenwiki.com/api/blueberrypai/getIndexChating.php",success: function (data) {console.log("网络请求执行完成");}})
}async function getData() {var result = await http();await getLog(result,2000);Hello();
}
getData();

本章作业

Generator 函数

第三节 模块的导入导出

在es5中,用module.exports和exports导出模块,用require引入模块。

es6新增export和export default导出模块,import导入模块。

3.1名字导出(name export)

名字导出可以在模块中导出多个声明。

export

export后必须跟语句, 何为语句, 如声明, for, if 等都是语句, export 不能导出匿名函数, 也不能导出某个已经声明的变量, 如:

export const bar = function() {}; // 合法
export bar; // 非法
export 1; // 非法
export function foo () {}; // 合法, 后跟的是声明语句
export { foo }; // 合法, 后面跟的{}理解为语句, 就像if后面的{}一样
export { foo as bar }; // 合法export { foo: foo }; // 非法, 后面的{}被解析成对象

3.2 默认导出(default export)

一个模块只能有一个默认导出,对于默认导出,导入的名称可以和导出的名称不一致,这对于导出匿名函数或类非常有用。

3.2.1 export default

export default在整个模块中只能出现一次, 后只能具体的值, 何为具体的值, 如1, 2, 3, 再比如一个函数声明(非表达式), 或者是一个类声明(与函数声明一个意思), 或者匿名函数, 只要是能用变量接受的都可以, 例子:

export default 1; // 合法
export default function foo() {}; // 合法, 因为function foo() {}
能被变量接受, 如 var bar = function foo() {}
export default const bar = 1; // 非法, 因为var a = const bar = 1 是不合法的
export default { foo }; // 合法, {} 被理解为一个对象
export default { foo: foo }; // 合法, 同上

3.2.2 import

import语法为:

import { x, y } from './test.js';import * as some from './test.js';  // 命名空间导入
import './test.js';import { default as test } from './test.js';

导入再导出

export { some } from './test.js';export * from './test.js';

导入后跟需要导入的绑定和模块说明符, 导入绑定的列表并非对象的解构, 二者并无关联, 导入的标识符很像const声明的变量, 不可更改, 也同时存在暂时性死区, 如有理解错误的地方还请不吝指教

第四节Class类

传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。这样的写法相对于其它传统面向对象语言来讲,很有一种独树一帜的感脚!非常容易让人困惑!
如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。构造函数示例:

  1. 当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
  2. 将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象
  3. 执行构造函数的代码。
  4. 返回新对象(后台直接返回);

4.1 类的定义

ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。如果将之前的代码改为ES6的写法就会是这个样子:

注意项

1.在类中声明方法的时候,千万不要给该方法加上function关键字

2.方法之间不要用逗号分隔,否则会报错

由下面代码可以看出类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!

console.log(typeof Person);//function
console.log(Person===Person.prototype.constructor);//true

以下代码说明构造函数的prototype属性,在ES6的类中依然存在着。
console.log(Person.prototype);//输出的结果是一个对象
实际上类的所有方法都定义在类的prototype属性上。代码证明下:

当然也可以通过prototype属性对类添加方法。如下:

还可以通过Object.assign方法来为对象动态增加方法

constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。

constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。

constructor中定义的属性可以称为实例属性(即定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(即定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值, true说明是实例属性,false说明不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

类的所有实例共享一个原型对象,它们的原型都是Person.prototype,所以proto属性是相等的

由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!

class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。

4.2 Class 的继承

Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

4.3 proxy

proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截

var proxy = new Proxy(target, handler);

new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为

· targetWithLog 读取属性的值时,实际上执行的是 logHandler.get :在控制台输出信息,并且读取被代理对象 target 的属性。

· 在 targetWithLog 设置属性值时,实际上执行的是 logHandler.set :在控制台输出信息,并且设置被代理对象 target 的属性的值

4.4 Proxy的作用

对于代理模式 Proxy 的作用主要体现在三个方面

  • 拦截和监视外部对对象的访问
  • 降低函数或类的复杂度
  • 在复杂操作前对操作进行校验或对所需资源进行管理

代码演示:

本期为大家带来的Web前端学习知识”Web前端:ES6是干什么的?(下)“介绍完毕了,想了解更多内容的小伙伴,关注我,更多内容等你看,我们下期再见!

前端为什么有的接口明明是成功回调却执行了.catch失败回调_Web前端:ES6是干什么的?(下)...相关推荐

  1. 前端为什么有的接口明明是成功回调却执行了.catch失败回调_前端进阶高薪必看-手写源码篇(高频技术点)...

    前言 此系列作为笔者之前发过的前端高频面试整理的补充 会比较偏向中高前端面试问题 当然大家都是从新手一路走过来的 感兴趣的朋友们都可以看哈 初衷 我相信不少同学面试的时候最怕的一个环节就是手写代码 大 ...

  2. 前端为什么有的接口明明是成功回调却执行了.catch失败回调_前端知识整理

    css 异步编程: 传统的异步解决方案采用回调函数和事件监听的方式 新方案: ES6的新语法Promise promise就是一个容器,里面包含着一个未来才会结束的事件(通常是一个异步操作)的结果.比 ...

  3. webstorm前端调用后端接口_软件测试面试题:怎么去判断一个bug是前端问题还是后端问题...

    大家好,在软件测试面试过程中,经常有面试官问到这个问题,那我们应该如何回答才好呢?少废话,直接看答案: 答案: 在页面上发现bug之后,要想判断这个问题属于后端还是前端,我就需要来判断这个页面背后调用 ...

  4. H5的jsapi微信支付:wx.chooseWXPay,ios手机在支付成功后不执行success中的回调函数

    对于iOS客户端支付成功后不进入chooseWXPay函数success的问题原因是:目前没有得到解答 临时解决方案: 支付成功后,安卓和iOS的返回都是{"errMsg":&qu ...

  5. 前端中怎么把网页多个文件夹的内容整合成一个_web前端学习笔记

    web前端的定义:是面向用户(浏览者)的互联网技术统称.主要包括Web界面的结构.Web界面的外观视觉表现以及Web界面的交互实现. HTML结构语言:超文本标记语言. Web前端的分类:前端设计和前 ...

  6. Nginx解决前端调用后端接口跨域问题

    Nginx解决前端调用后端接口跨域问题 参考文章: (1)Nginx解决前端调用后端接口跨域问题 (2)https://www.cnblogs.com/wangymd/p/11200746.html ...

  7. 前端与后端接口的交互案例

    一.案例描述 1,前端页面提供用户名,密码输入框. 2,通过Ajax发送请求到后端Serlvet. 3,后端Serlvet处理请求,根据输入的用户名和密码返回给前端不同信息 前端访问后端接口通过后端提 ...

  8. Java回调网址_极光短信- 回调接口 - 极光文档

    回调接口 设置并校验回调地址: 回调消息格式说明: 测试回调功能的方法: 设置回调地址 功能说明 设置并校验回调地址 操作路径 Step1:登入控制台 Step2:进入应用模版 Step3:右侧菜单中 ...

  9. App前端及后端接口,模拟数据及返回值

    App前端及后端接口,模拟数据 :接口文档 目录 1. 全局状态码 6 2. 前台 7 2.1. 首页 7 2.1.1. 商品分类列表接口 7 2.1.2. 展示轮播图接口 9 2.1.3. 展示广告 ...

最新文章

  1. ZBar与ZXing使用后感觉
  2. 标准功能模块组件 -- 内部联络单组件,内部邮件组件,提高多人异地协同办公效率...
  3. Linux Shell 只列出目录的方法
  4. OpenStack在dashboard界面点击管理员网络,服务器页面出错
  5. php学习---环境搭建安装 编译器的安装
  6. c++ 数组换行_C语言的数组的构建与打印
  7. Servlet获取URL地址
  8. 如何写好接口(php写app移动端接口示例)
  9. 二叉树,建树,前序,中序,后序,递归 非递归
  10. android 屏幕管理软件,Android Screencast下载
  11. node.js安装express(零起点搭建本地测试服务器)- 教程篇
  12. 潭州课堂25班:Ph201805201 第十二课 new方法,定制属性访问,描述符与装饰器 (课堂笔记)...
  13. Yarn分布式集群操作系统
  14. 【数学建模】基于matlab GUI干线交通控制方法【含Matlab源码 1259期】
  15. 【源码】VB6聊天机器人
  16. 美信科技监控易:智慧高校一体化综合监控解决方案
  17. 编程方式实现Excel转为JPG/PDF等格式
  18. 【语音识别】基于HMM实现中文语音识别含Matlab源码
  19. 《菊与刀》读后感作文5000字
  20. 苹果各版本手机更换电池的视频

热门文章

  1. 动态规划求解序列问题(LIS、JLIS)
  2. Symfony常用指令(收藏版)
  3. JTable调整列宽
  4. 对新手的忠告:拒绝创意,回归基础
  5. 使用studio2005写单元测试
  6. boot mybatis mysql_SpringBoot+Mybatis+MySql学习
  7. mysql数据库上传ftp服务器中_备份部分mysql表并上传至指定ftp服务器目录中
  8. linux shell 变量 管道,linux下shell,变量,管道,重定向等基础知识及技巧
  9. 定时任务scheduleAtFixedRate设定每天某个时刻执行
  10. python中的列表分片详解_python列表与元组详解实例