目录

ES6: (ECMAScript第六个版本)

1. 解构(destruct)

2. class

3. Promise


ES6: (ECMAScript第六个版本)

1. 解构(destruct)

在旧 js 中,要想使用对象中的成员或数字中的元素,必须带着"对象名."或"数组名[ ]"前缀。但是在实际开发中,对象或数组的嵌套结构可能很深,这样的话前缀就可能写很长: "对象名.子对象名.子对象名....",非常麻烦。而解构方式就是用来来减少数组或对象的嵌套结构,便于使用。解构分为三种:

(1)数组解构

数组解构用于从一个复杂的数组中只提取出需要的元素单独使用,格式如下:

 var [变量1, 变量2, ...] = 数组;

右边数组中相同下标位置的元素值会自动赋值给=左边相同下标位置的变量,一一对应;

变量1 = 数组[0];

变量2 = 数组[1];

要注意此处的 [ ] 并不带表创建一个新数组,仅仅是将个变量“装扮”成数组的样式。

举例:从数组中解构出年、月、日;

<script>var arr = [2021, 9, 3, 33];// 解构// 提取出数组中年月日三个值使用// var [a, b, c] = arr;// 如果不要年,只要月日var [, b, c] = arr;// console.log(`今年是${a}年`);console.log(`本月是${b}月`);console.log(`今天是${c}日`);</script>

(2)对象解构

对象解构用于从一个大的对象中只提取出个别属性值单独使用,格式如下:

var { 属性名1:变量1, 属性名2:变量2,... } = 对象;

当 : 左右两边的名字相同时,ES6为我们提供了简写方式:

如果 : 左边的属性名刚好和 : 右边的变量名相同,则只需要写一个即可;此时一个名字就起到了两两个作用,既当属性名进行配对、又当变量名进行接值。简写后格式如下:

var {属性名1, 属性名2, ...} = 对象;

举例:解构出对象中的姓名和年龄单独使用;

<script>var lilei = {sname: "李雷",sage: 21}// 解构// var {sname: sname,sage: sage} = lilei;// 简写//一个名字两用:既当属性名配对;又当变量名接值var {sname,sage} = lileiconsole.log(`我叫${sname},今年${sage}岁`);</script>

(3)参数解构

单靠参数默认值,无法解决任意一个形参不确定有没有的情况。只要实参值不确定没有,但是又要求实参值必须传给指定的形参,顺序不能乱,就要用用参数解构。格式如下:

//定义函数时: function 函数名({属性名1: 形参1, 属性名2: 形参2, ... : ...
}){函数体
}//调用函数时: 函数名({属性名1: 实参值1, 属性名2: 实参值2, ... : ...
})

简写后格式如下:

//定义函数时:function 函数名({属性名1 = 默认值1, 属性名2 = 默认值2, ... : ...
}){函数体
}//调用时:函数名({属性名1: 实参值1, 属性名2: 实参值2, ... : ...
})

举例:定义订套餐函数,用户可任意更换套餐中菜品;

<script>// 定义一个点套餐的函数function order({zhushi = "香辣鸡腿堡",xiaochi = "烤鸡翅",yinliao = "可乐"}) {console.log(`您点的套餐为:主食:${zhushi}小吃:${xiaochi}饮料:${yinliao}`);}// a点默认套餐order({});// b自定order({zhushi: "牛肉汉堡",xiaochi: "鸡米花",yinliao: "雪碧"})// c只换主食order({zhushi: "烤全鸡"})// d只换小吃order({xiaochi: "正新鸡排"})</script>

打印结果如下:

2. class

在旧 js 中,构造函数和原型对象是分开定义的,这样不符合"封装"概念;class 是程序中专门集中保存一种类型的所有子对象的统一属性结构和方法定义的程序结构。所以今后只要在 es6 中创建一种新的类型,包含构造函数 + 原型对象方法,都要用 class 来创建。

定义 class 的方法:

a. 先用 class{ } 包裹原构造函数+原型对象方法;(虽直接放在 class{} 内的方法定义,其实还是保存在原型对象中的)

b. 原构造函数名升级为整个 class 的名字,所有构造函数统一更名为 "constructor";

c. 原型对象中的方法,不再加 prototype 前缀,也不用=function,直接简写为: 方法名(){ ...}。

使用 class:

var 对象名=new class名(属性值,...);

虽说用了 class,但本质并没有变:构造函数中的属性,依然会成为子对象的自有属性;直接定义在 class 中的方法,依然保存在子对象的原型对象中;子对象依然使用 _ _proto_ _ 指向原型对象。

举例:定义学生类型 class;

<script>// 定义学生类型,描述所有学生的统一结构和功能class Student {constructor(sname, sage) {this.sname = sname;this.sage = sage;}intr() {console.log(`我是${this.sname},我今年${this.sage}岁。`);}}// 创建一个学生对象var lilei = new Student("李雷", 21);console.log(lilei);lilei.intr();</script>

但是上述用法也有一定的不足,若多个子对象共用相同的属性值,属性值应该放在哪里?

虽然直接在 class 中定义的方法,都默认保存在原型对象中。但是直接在 class 中定义的属性,却不会成为共有属性,不会保存在原型对象中,而是成为每个子对象的自有属性。

在旧 js 中,是和共有方法一起放在原型对象中;而为了和其它主流开发语言尽量一致,ES6的 class 放弃了在原型对象中保存共有属性的方式。而是改为用静态属性 static 保存!

静态属性

不需要创建子对象,单靠类型名就可直接访问的属性,就称为静态属性;今后在ES6中,如果希望所有子对象,都可使用一个共同的属性值时,都要用静态属性代替原来的原型对象属性。

静态属性定义与调用格式如下:

//定义静态属性: class 类型名{static 共有属性名=属性值... ...
}//访问静态属性: 类型名.静态属性

注意访问静态属性时不可写成 this.静态属性 。

标有 static 的静态属性,都保存在构造函数对象身上。因为构造函数在程序中不会重复,所以静态属性也不会重复;任何时候,任何地点,访问一个类型的静态属性,永远访问的都是同一份!

举例:使用静态属性替所有子对象保存共用的班级名;

<script>//定义学生类型,描述所有学生的统一结构和功能class Student {// 定义静态属性,可以多个对象共用static className = "初一2班";constructor(sname, sage) {this.sname = sname;this.sage = sage;}intr() {console.log(`我是${this.sname},我今年${this.sage}岁`);}}// 创建学生对象var lilei = new Student("李雷", 21);var hmm = new Student("韩梅梅", 20)console.log(lilei);console.log(hmm);lilei.intr();hmm.intr();// 一年后,初一升初二Student.className = "初二2班";lilei.intr();hmm.intr();console.log(Student); //log 默认输出的是Student构造函数的函数体(内容),不是对象结构console.dir(Student); //dir 不输出函数的内容,而是输出对象在内存中的存储结构</script>

两种类型间的继承

两种 class 之间可能包含部分相同的属性结构和方法定义,这时候就应该用到继承。

进行继承的方法:

(1)额外创建一个父级 class;

i. 父级 class 的构造函数中包含子类型 class 中相同部分的属性结构定义;

ii. 父级 class 的原型对象中包含子类型 class 中相同部分的方法定义;

iii. 既然父级 class 中保存了相同的属性结构和方法定义,则子类型 class 中,就可以删除所有重复的属性结构和方法定义;

(2)让子类型 class 继承父类型的 class;

i. 设置子类型的原型对象继承父类型的原型对象;

class 子类型 extends 父类型{ ... }

ii. 使用 super 关键字,调用父级的父级类型的构造函数。

举例:使用类型间继承,实现飞机大战游戏中敌机和降落伞类型的定义,并创建敌机对象和降落伞对象;

<script>//定义爷爷class,保存共有属性结构和方法class enemy {constructor(x, y) {this.x = x;this.y = y;}fly() {console.log(`目标飞到x=${this.x},y=${this.y}的位置。`);}}class Plane extends enemy {constructor(x, y, score) {super(x, y);this.score = score;}getScore() {console.log(`击落敌机得${this.score}分!`);}}class Jls extends enemy {constructor(x, y, ming) {super(x, y);this.ming = ming;}getMing() {console.log(`击落降落伞,得生命值${this.ming}!`);}}var p1 = new Plane(255, 255, 20);var p2 = new Jls(222, 125, 1)p1.fly();p1.getScore();p2.fly();p2.getMing();</script>

3. Promise

promise 是专门保证多个异步任务必须顺序执行的一种特殊方式;在实际开发中,经常需要让多个异步任务顺序执行,而单纯先后调用多个异步函数的话,异步函数各自执行各自的,互不干扰,互相之间也不会等待,是错误的。

解决以上问题可以用回调函数,举例:使用回调函数保证多个异步任务顺序执行;

<script>function zhangsan(box) {console.log(`张三起跑!`);setTimeout(function () {console.log(`张三跑到了终点!`);box();}, 6000)}function lisi(box) {console.log(`李四起跑!`);setTimeout(function () {console.log(`李四跑到了终点!`);box();}, 4000)}function wangwu() {console.log(`王五起跑!`);setTimeout(function () {console.log(`王五跑到了终点!`);}, 2000)}zhangsan(function () {lisi(function () {wangwu();});});</script>

但是用回调函数的话,如果要先后执行的任务多了,就会形成很深的嵌套结构——回调地狱,不仅极其不优雅,而且极其不便于维护。

这种情况下,就需要用到 promise 来代替回调函数。步骤:

(1)定义前一项任务

function 前一项任务(){return new Promise(function(开关){原异步任务异步任务最后一句话调用开关()//开关通向后面的.then,自动执行.then中的下一项任务})}

(2)连接前后两个异步任务

前一项任务().then( 后一项任务 ) //注意最后一项任务不要再加()

两个任务之间也可以进行传参:

//前一项任务: function 前一项任务(){return new Promise(function(开关){var 变量=值调用开关( 变量 )})
}//后一项任务: function 后一项任务(形参){//形参=前一项任务中的变量值
}

举例:使用 Promise 模拟接力跑传接力棒;

<script>function zhangsan() {return new Promise(function (open) {var JieLiBang = "张三的接力棒";console.log(`张三拿着${JieLiBang}起跑!`);setTimeout(function () {console.log(`张三跑到了终点!`);open(JieLiBang);}, 6000)})}function lisi(JieLiBang) {return new Promise(function (open) {console.log(`李四拿着${JieLiBang}起跑!`);setTimeout(function () {console.log(`李四跑到了终点!`);open(JieLiBang);}, 4000)})}function wangwu(JieLiBang) {console.log(`王五拿着${JieLiBang}起跑!`);setTimeout(function () {console.log(`王五跑到了终点!`);}, 2000)}zhangsan().then(lisi).then(wangwu);</script>

(3)错误处理,格式如下:

//前一项任务: function 前一项任务(){return new Promise(function(成功的开关, 失败的开关){var 变量=值原异步任务异步任务最后一句话如果异步任务执行成功调用成功的开关( 变量 )//此处开关通.then(),自动执行.then中的下一项任务否则如果一部任务执行失败调用失败的开关(错误提示信息)//此处开关通最后的.catch(),后续.then()不再执行。})}//调用时: 前一项任务().then(下一项任务).then(...).catch(function(错误提示信息){ 错误处理代码 })

举例:假设有人在跑步过程中摔倒了,要添加错误处理;

<script>function zhangsan() {return new Promise(function (resolve, reject) {var JieLiBang = "张三的接力棒";console.log(`张三拿着${JieLiBang}起跑!`);setTimeout(function () {if (Math.random() < 0.5) {console.log(`张三拿着${JieLiBang}到达了终点!`);resolve(JieLiBang);} else {reject(`张三摔倒了!!`);}}, 6000)})}function lisi(JieLiBang) {return new Promise(function (resolve, reject) {console.log(`李四拿着${JieLiBang}起跑!`);setTimeout(function () {if (Math.random() < 0.5) {console.log(`李四拿着${JieLiBang}跑到了终点!`);resolve(JieLiBang);} else {reject(`李四摔倒了!!`);}}, 4000)})}function wangwu(JieLiBang) {console.log(`王五拿着${JieLiBang}起跑!`);setTimeout(function () {console.log(`王五跑到了终点!`);}, 2000)}zhangsan().then(lisi).then(wangwu).catch(function (msg) {console.log(msg);console.log(`出现紧急状况,比赛终止!!!!`);});</script>

(4)Promise对象三大状态 (记忆)

a:当异步任务执行过程中,整个 new Promise() 对象处于 pending(挂起)状态;

b:当异步任务成功执行完,调用成功的开关函数时,整个 new Promise() 对象切换为 fulfilled(成功)状态,new Promise() 会自动调用 .then() 执行下一项任务;

c:当异步任务执行出错,调用失败的开关函数,整个 new Promise() 对象切换为 rejected(出错)状态,new Promise() 会自动调用 .catch() 执行错误处理代码。

在行业中,这两个开关常用(规范):

正确的开关:resolve(同意继续)

失败的开关:reject(拒绝继续)


JavaScript高级 终!

JS 高级(七)ES6解构、class、promise相关推荐

  1. js之删除对象中的属性——delete、es6解构赋值、自执行匿名函数

    js之删除对象中的属性--delete.es6解构赋值.自执行匿名函数 实例 const person = {name: '李世民',gender: 'male',age: 24 };// 删除目标对 ...

  2. 菜鸟也谈js(一)——ES6解构对象篇

    前言 为什么我会在开篇谈这样一个low到爆的问题呢?这是因为一个伟大的错误,多么痛的领悟!从前,我深深的以为,后台是权威,后台的数据必须是对的.直到有一天测试给我反馈了一个bug,我的页面崩溃了... ...

  3. ES6 解构赋值详解

    解构赋值是对赋值运算符的扩展,可以将属性/值从对象/数组中取出,赋值给其他变量. 一.数组的解构赋值 1.基本用法 只要等号两边的模式相同,左边的变量就会被赋予对应的值. let [a, [[b], ...

  4. ES6解构赋值原理详解

    ES6解构赋值 ES6变量的解构赋值本质上是"模式匹配",只要等号两边的模式相同,左边的变量就会被赋予匹配的右边的值,如果匹配不成功变量的值就等于undefined 数组的解构赋值 ...

  5. 前端学习必备之ES6解构赋值的常见用法

    1.解构赋值可以轻松获取对象或者数组中的数据 var jsonData = {data: "111",data2: ["test","test2&qu ...

  6. ES6 解构赋值的用法笔记

    1.概念:解构赋值可以理解为对赋值运算符的一种扩展.它主要针对数组或者 对象进行模式匹配,然后对模式中的变量进行赋值. 2.特性:采用ES6解构赋值的方式可以代码的可读性更高.代码书写更加简洁.清晰. ...

  7. es6解构--简化代码

    第一段代码直接用 import { Radio } from 'antd'; render() {return(<Radio.Group value={size} onChange={this. ...

  8. [OHIF-Viewers]医疗数字阅片-医学影像-es6解构赋值-const{}=-let{}=

    [OHIF-Viewers]医疗数字阅片-医学影像-es6解构赋值-const{}=-let{}= 解构赋值语法是一种 Javascript 表达式.通过解构赋值, 可以将属性/值从对象/数组中取出, ...

  9. ES6解构赋值: ES6...转为ES5的写法

    es6的特性,主要用于 数组和对象的析构 直接上问题: 因为chrome低版本(用的55版本)不支持es6...的下面这种写法, 需要转为es5写法 function calcLinePaths() ...

  10. 聊聊 ES6 解构(下)

    大家好,我是Chuck,一个不那么正经却热爱前端的孩儿. 昨晚睡觉的时候,突然想起来点事情,点开了掘金,一看上文,这是什么东西?怎么忘了好多东西呢? 这篇文章接上文 聊聊 ES6 解构|8月更文挑战. ...

最新文章

  1. hitTest和pointInside方法
  2. Xcode @property attributes (nonatomic, copy, st...
  3. python动态心形代码-Python数学方程式画心型图案源码示例
  4. python需要php吗-做网站用php还是python
  5. 天刀各大区服务器位置,数据帝玩家统计 天刀全区活跃地图展示
  6. Jmeter+ant+Jenkins构建接口自动化测试时构建失败 提示:Fatal Error! 字符引用 #原因...
  7. 已知一个特殊字符的 unicode 编码值,如何在 ABAP 里打印出这个特殊字符?
  8. hdoj 1114 Piggy-Bank(完全背包+dp)
  9. vue element table
  10. Gradle 3.0.0设置Apk文件输出命名
  11. python爬虫接单设置_Python 爬虫之设置ip代理,设置User-Agent,设置请求头,设置post载荷...
  12. HTML的iframe标签的滚动条
  13. JavaSE_1   基本概念
  14. matlab whos命令
  15. 迁移学习全面指南:概念、应用、优势、挑战
  16. Java 8 新特性(二)流类库
  17. 收藏的一些github开源项目,在这里记录一下
  18. Python常用的一些库(仅供参考)
  19. 极点五笔linux,Ubuntu 11.10安装极点五笔
  20. 数据挖掘概念与技术(第三版)课后答案——第三章

热门文章

  1. 经典工作自我鉴定范文/实习自我鉴定表
  2. 关于 uintptr_t和intptr_t 类型
  3. 打开5555调试端口
  4. 1 error and 0 warnings potentially fixable with the `--fix` option.
  5. 想要了解大厂PM吗,来看看这几款软件
  6. WarGame bandit
  7. cad在线转换_手绘稿画好后我熬了一个通宵描图,结果组长给我说可以一键生成CAD!...
  8. 将python脚本打包为exe可执行文件
  9. 外贸客户电话和邮件地址的收集
  10. 多旋翼无人机组成(小白上路)