EmmmuaCode EmmmuaCode
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)

wufan

海内存知己,天涯若比邻。
首页​
导航🚀​
  • 数据结构
  • 计算机网络
  • Java基础

    • JavaSE
    • JVM虚拟机
    • JUC并发编程
  • JavaWeb

    • Servlet
    • MVC
    • filter|listener
  • HTML
  • CSS
  • JavaScript
  • Vue
  • uni-app
  • Spring5
  • SpringMVC
  • SpringBoot2
  • SpringCloud
  • SpringSecurity
  • 搜索引擎

    • ElasticSearch
  • 消息队列

    • RabbitMQ
  • 服务器

    • Nginx🌐
  • 服务框架

    • Dubbo
  • Python基础
  • 数据分析
  • Hadoop
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • NoSQL数据库概论
    • Redis
    • MongoDB
    • HBase
  • 框架

    • MyBatis
    • MyBatis-Plus
    • ShardingSphere
  • 部署

    • Linux
    • Docker
  • 管理

    • Maven
    • Git
  • 友情链接
  • 优秀博客文章
  • 索引

    • 分类
    • 标签
    • 归档
  • 其他

    • 关于
Github (opens new window)
  • HTML

    • HTML
  • CSS

    • CSS
    • CSS-02
    • CSS-03
    • CSS-浮动(float)
    • CSS-定位(position)
    • CSS3 新特性
    • CSS3 2D和3D的使用
  • JavaScript

    • JavaScript
    • JavaScript 变量
    • JavaScript 数据类型
    • JavaScript 运算符与语句
    • JavaScript For循环与数组
    • JavaScript 函数
    • JavaScript 对象
    • ES6
      • 命令行工具
        • CMD命令行
        • PowerShell
      • ECMAScript 6 简介
        • ECMAScript 和 JavaScript 的关系
        • 名称详解
        • 语法提案的批准流程
        • ES6带来的新特性
      • Nodejs环境安装
        • Nodejs简介
        • Nodejs安装
        • 大量的库
        • npm镜像
      • Babel转码器
        • 转码示例
        • Babel安装流程
        • 第一步:安装 Babel
        • 第二步:配置文件.babelrc
        • 第三步:转码规则
        • 第四步:将规则加入.babelrc
        • Babel命令行转码
      • Let 命令
        • let块级作用域
        • let不存在变量提升
        • let不允许重复声明
      • Const 命令
      • var 、let、const总结
      • 对象解构赋值
      • 字符串扩展
        • 字符串Unicode 表示法
        • Unicode
        • 字符串遍历器接口
        • 模板字符串
      • 字符串新增方法
        • includes(), startsWith(), endsWith()
        • repeat()
        • padStart(),padEnd()
        • trimStart(),trimEnd()
        • at()
      • 数组扩展_扩展运算符
        • 替代函数的 apply 方法
        • 合并数组
      • 数组扩展_新增方法
        • Array.from()
        • arguments
        • 元素集合
        • 类似数组的对象
        • Array.of()
      • 对象的扩展
        • 属性的简洁表示法
        • 属性名表达式
        • 对象的扩展运算符
      • 函数的扩展_箭头函数
        • 基本用法
        • 使用注意点
      • Set 数据结构
        • 基本用法
        • size属性
      • Set 数据结构方法
        • add()
        • delete()
        • has()
        • clear()
      • Promise 对象
        • 基本概念
        • 基本用法
        • 加载图片资源例子
      • Promise对象_Ajax实操
      • Async 函数
        • 示例代码
        • 基本语法
        • 异步应用
      • Class 的基本语法
        • 类的由来
        • constructor 方法
        • 类的实例
        • 注意点
        • 不存在提升
      • Class属性与方法
        • 实例方法
        • 实例属性
        • 静态方法
        • 静态属性
      • Class 的继承
        • 基础用法
      • Module 的语法
        • 测试方式
        • export 命令
        • import 命令
        • export default 命令
  • Vue

    • Vue 快速上手
  • uni-app

    • 从基础概念到uni-app项目搭建
    • 页面优化与数据处理的深入实践
    • Vuex 的应用与购物车功能实现
    • 购物车与结算区域的功能实现与优化
    • 购物车与结算区域的深入优化与功能完善
    • 微信支付功能的实现与流程
  • studynotes
  • web
  • JavaScript
wufan
2024-02-01
目录

ES6

# 命令行工具

在正式讲解ES6新特性之前,我们需要了解一些命令行工具,在日后的课程中,我们会经常用到命令行

常用命令行工具有两种

  1. CMD 命令行工具
  2. PowerShell 命令行工具

# CMD命令行

  1. 打开命令行窗口
    1. win:左下角开始,找到运行,点击,输入cmd,回车
    2. win:win+r 快速打开命令行窗口
    3. mac:command + 空格,输入terminal
  2. 选择盘符:盘符名加冒号E:
  3. 查看盘符及目录下文件与文件夹:win:dir mac:ls
  4. 清空命令行信息:win:cls mac:clear
  5. 进入文件夹或目录:cd 文件夹名称
  6. 返回到上一级目录:cd ../
  7. 快速补全目录或文件夹名称:tab
  8. 创建文件夹:mkdir 文件夹名称
  9. 查看历史输入过的命令:上下按键

# PowerShell

  1. 打开方式
    1. 在开始位置搜索PowerShell打开
    2. 在对应目录按住shift+右键,打开
  2. 其他保持一直

实时效果反馈

1. 如何快速打开CMD命令行工具:

A win+R

B win+E

C win+P

D win+L

2. CMD命令行中进入文件夹或目录:

A win+R

B mkdir 文件夹名称

C cd ../

D cd 文件夹名称

答案

1=>A 2=>D

# ECMAScript 6 简介

# ECMAScript 和 JavaScript 的关系

ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现,常场合,这两个词是可以互换的。

# 名称详解

ECMAScript 6(以下简称 ES6)是 JavaScript 语言的标准,在 2015 年 6 月发布。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

版本 官方名称 发布日期
ES1 ECMAScript 1 1997
ES2 ECMAScript 2 1998
ES3 ECMAScript 3 1999
ES4 ECMAScript 4 从未发布过
ES5 ECMAScript 5 2009
ES5.1 ECMAScript 5.1 2011
ES6 ECMAScript 2015(ECMAScript 6) 2015
ES7 ECMAScript 2016 2016
ES8 ECMAScript 2017 2017
... ... ...

因此,ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等

# 语法提案的批准流程

任何人都可以向标准委员会(又称 TC39 委员会)提案,要求修改语言标准。

一种新的语法从提案到变成正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准。

  • Stage 0 - Strawman(展示阶段)
  • Stage 1 - Proposal(征求意见阶段)
  • Stage 2 - Draft(草案阶段)
  • Stage 3 - Candidate(候选人阶段)
  • Stage 4 - Finished(定案阶段)

一个提案只要能进入 Stage 2,就差不多肯定会包括在以后的正式标准里面。ECMAScript 当前的所有提案,可以在 TC39 的官方网站GitHub.com/tc39/ecma262 (opens new window)查看。

# ES6带来的新特性

  1. let 和 const 命令
  2. 变量的解构赋值
  3. 字符串扩展
  4. 函数扩展
  5. 对象扩展
  6. 数组扩展
  7. 运算符扩展
  8. Promise对象
  9. Class
  10. Class 继承
  11. ...

# Nodejs环境安装

本节课为前置课程,在接下来的ES6课程中,我们需要先安装Nodejs环境

# Nodejs简介

Nodejs诞生于2009年,主攻服务器方向,使得利用JavaScript也可以完成服务器代码的编写

# Nodejs安装

Nodejs官网

https://nodejs.org/en/

Nodejs的安装与一般软件一样

# 大量的库

在安装Nodejs的同时,会附带一个npm命令,npm 是Node的包管理工具,这样正是接下来我们要用到的

npm 的简单结构有助于 Node.js 生态系统的激增,现在 npm 仓库托管了超过 1,000,000 个可以自由使用的开源库包

# npm镜像

由于服务器在国外,所以下载速度比较慢,我们可以用国内的镜像

阿里镜像地址

https://npmmirror.com/

在命令行运行如下命令即可

npm install -g cnpm --registry=https://registry.npmmirror.com
1

看到如下信息,代表安装成功

# Babel转码器

Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持

浏览器支持性查看

https://caniuse.com/

Babel官网

https://babeljs.io/

# 转码示例

原始代码用了箭头函数,Babel 将其转为普通函数,就能在不支持箭头函数的 JavaScript 环境执行了

// 转码前
input.map(item => item + 1);

// 转码后
input.map(function (item) {
  return item + 1;
});
1
2
3
4
5
6
7

# Babel安装流程

# 第一步:安装 Babel

npm install --save-dev @babel/core
1

# 第二步:配置文件.babelrc

Babel 的配置文件是.babelrc,存放在项目的根目录下。使用 Babel 的第一步,就是配置这个文件。

该文件用来设置转码规则和插件,基本格式如下

{
  "presets": [],
  "plugins": []
}
1
2
3
4

# 第三步:转码规则

presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装

npm install --save-dev @babel/preset-env
1

# 第四步:将规则加入.babelrc

{
    "presets": [
      "@babel/env"
    ],
    "plugins": []
}
1
2
3
4
5
6

# Babel命令行转码

Babel 提供命令行工具@babel/cli,用于命令行转码

npm install --save-dev @babel/cli
1

基本用法如下

# 转码结果输出到标准输出
$ npx babel example.js

# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ npx babel example.js --out-file compiled.js
# 或者
$ npx babel example.js -o compiled.js

# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ npx babel src --out-dir lib
# 或者
$ npx babel src -d lib
1
2
3
4
5
6
7
8
9
10
11
12
13
14

实时效果反馈

1. Babel的作用是什么:

A Babel是ES6的一部分,是ES6的新特性

B Babel是ES6的转码器,可以将 ES6 代码转为 ES5 代码

C Babel是配置文件,配置ES6环境

D Babel是ES5的基础知识

2. 下列哪个是安装Babel命令转码工具:

A npm install --save-dev @babel/core

B npm install --save-dev @babel/preset-env

C npm install --save-dev @babel/cli

D npx babel example.js

答案

1=>B 2=>C

# Let 命令

ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

# let块级作用域

{
  let itbaizhan = 10;
  var sxt = 1;
}

itbaizhan // ReferenceError: itbaizhan is not defined.
sxt // 1
1
2
3
4
5
6
7

for循环的计数器,就很合适使用let命令

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);
// ReferenceError: i is not defined
1
2
3
4
5
6

对比var和let在循环中的应用

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10
1
2
3
4
5
6
7

上面代码,输出的10,而我们期待的是6

[scode type="blue" size="simple"]

在上述代码中,使用了一个闭包来创建一个数组a。在循环期间,每个函数都被分配给数组a中的相应元素,并且每个函数访问变量i的引用。当循环结束时,变量i的值为10。 因此,当函数执行时,它们会输出变量i的当前值,也就是10。因此,输出结果为10而不是6。

[/scode]

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6
1
2
3
4
5
6
7

上面代码,输出的6

[scode type="blue" size="simple"]

在这个例子中,使用了ES6的let关键字来声明循环变量i。与使用var相反,每次迭代都会创建一个新的变量实例,并且在每个函数闭包中捕获对该实例的引用。因此,当函数执行时,它们引用的是其闭包中的变量实例,而不是循环的单个变量。

[/scode]

# let不存在变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用

为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
1
2
3
4
5
6
7

# let不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}
1
2
3
4
5
6
7
8
9
10
11

实时效果反馈

1. 下列那个不是Let的特性:

A Let是块级作用域

B Let不存在变量提升

C Let不允许重复声明

D Let和Var一样并没有区别

答案

1=>D

# Const 命令

const声明一个只读的常量。一旦声明,常量的值就不能改变

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.
1
2
3
4
5

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值

const foo;
// SyntaxError: Missing initializer in const declaration
1
2

const的作用域与let命令相同:只在声明所在的块级作用域内有效

if (true) {
  const MAX = 5;
}

MAX // Uncaught ReferenceError: MAX is not defined
1
2
3
4
5

const命令声明的常量也是不存在提升

if (true) {
  console.log(MAX); // ReferenceError
  const MAX = 5;
}
1
2
3
4

const声明的常量,也与let一样不可重复声明

var message = "Hello!";
let age = 25;

// 以下两行都会报错
const message = "Goodbye!";
const age = 30;
1
2
3
4
5
6

实时效果反馈

1. 下列const特性描述错误的是:

A const命令声明的常量不提升

B const命令不可重复声明

C const命令是块级作用域

D const命令声明可以改变

答案

1=>D

# var 、let、const总结

在 JavaScript 中,var、let 和 const 都可以用来声明变量,它们之间有以下几个区别:

  1. 变量提升:使用 var 声明的变量会被提升到作用域的顶端,而 let 和 const 不会。这意味着在 var 声明变量前面进行访问时,该变量的值是 undefined;但是,在使用 let 或 const 声明的变量之前进行访问会得到一个 ReferenceError 错误。
  2. 作用域:var 的作用域是函数作用域或全局作用域,而 let 和 const 的作用域是块级作用域。因此,在使用 let 或 const 声明变量时,只能在 {} 内部访问该变量,超出这个范围会抛出错误。
  3. 可重复声明:使用 var 声明的变量可以在同一作用域内多次声明,而 let 和 const 不允许在同一作用域内重复声明。
  4. 初始值:var 和 let 变量声明时可以不赋初始值,此时变量的值为 undefined;而 const 必须在声明时就给变量赋初始值,否则会抛出 SyntaxError 错误。
  5. 可更改性:var 和 let 声明的变量的值可以被修改,而 const 声明的变量的值不能被重新赋值。

综上所述,let 和 const 相对于 var 更符合现代 JavaScript 的编码习惯。在声明变量时,优先考虑使用 const,因为它能够保证变量的值不会被更改,在需要修改变量时再使用 let。

# 对象解构赋值

解构可以用于对象

let {name,age} = {name:"iwen",age:20};
1

温馨提示

对象的属性没有次序,变量必须与属性同名,才能取到正确的值

let {age,name} = {name:"iwen",age:20};
age // 20
1
2
let {sex,age,name} = {name:"iwen",age:20};
sex // undefined
1
2

对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量

let { random,floor } = Math;
let { log } = console;
1
2

注意事项,如果要将一个已经声明的变量用于解构赋值,必须非常小心

let hello = "Hello";
let { hello } = {hello:"hello"}; // 报错

let hello = "Hello";
({ hello } = {hello:"hello"}); // 正确
1
2
3
4
5

实时效果反馈

1. 下列对象解构赋值的代码,输出结果是多少:

let hello = "Hello";
let { hello } = {hello:"hello"}; 
console.log(hello);
1
2
3

A hello

B Hello

C 报错

D undefined

答案

1=>C

# 字符串扩展

# 字符串Unicode 表示法

ES6 加强了对 Unicode 的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。

# Unicode

统一码(Unicode),也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

"\u0061"
// "a"
1
2

# 字符串遍历器接口

for...of循环遍历

for (let i of 'itbaizhan') {
  console.log(i);
}
1
2
3

# 模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

let url = "www.itbaizhan.com"
let h1 = "<a href='"+ url +"'>itbaizhan</a>"
let h2 = `<a href='${url}'>itbaizhan</a>`
1
2
3

实时效果反馈

1. 下列字符串模板,表示正确的是:

A <img src='{url}' alt='{tip}'>

B <img src='${url}' alt='${tip}'>

C <img src='$url' alt='$tip'>

D <img src='url' alt='tip'>

答案

1=>B

# 字符串新增方法

# includes(), startsWith(), endsWith()

传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

  1. includes():返回布尔值,表示是否找到了参数字符串
  2. startsWith():返回布尔值,表示参数字符串是否在原字符串的头部
  3. endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部
let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
1
2
3
4
5

这三个方法都支持第二个参数,表示开始搜索的位置

let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
1
2
3
4
5

# repeat()

repeat方法返回一个新字符串,表示将原字符串重复n次。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
1
2
3

# padStart(),padEnd()

ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
1
2
3
4
5

# trimStart(),trimEnd()

ES2019对字符串实例新增了trimStart()和trimEnd()这两个方法。它们的行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。

const s = '  itbaizhan  ';

s.trim() // "itbaizhan"
s.trimStart() // "itbaizhan  "
s.trimEnd() // "  itbaizhan"
1
2
3
4
5

# at()

at()方法接受一个整数作为参数,返回参数指定位置的字符,支持负索引(即倒数的位置)。

const str = 'hello';
str.at(1) // "e"
str.at(-1) // "o"
1
2
3

温馨提示

如果参数位置超出了字符串范围,at()返回undefined

实时效果反馈

1. 下列字符串方法中,那个可以判断是否包含某个字符串:

A includes()

B repeat()

C padStart()

D at()

答案

1=>A

# 数组扩展_扩展运算符

扩展运算符(spread)是三个点(...)。将一个数组转为用逗号分隔的参数序列

console.log(...[1, 2, 3])
// 1 2 3

console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
1
2
3
4
5

# 替代函数的 apply 方法

由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了

// ES5 的写法
Math.max.apply(null, [14, 3, 77])

// ES6 的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);
1
2
3
4
5
6
7
8

# 合并数组

扩展运算符提供了数组合并的新写法

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
1
2
3
4
5
6
7
8
9
10
11

实时效果反馈

1. 下列代码,获取数组的最大值,划横线处填写的代码是:

Math.max(___[14, 3, 77])
1

A apply

B call

C ...

D concat

答案

1=>C

# 数组扩展_新增方法

# Array.from()

Array.from方法用于将类数组转为真正的数组

温馨提示

常见的类数组有三类:

  1. arguments
  2. 元素集合
  3. 类似数组的对象

# arguments

function add(){
    let collect = Array.from(arguments);
    collect.push(40);
    console.log(collect);
}
add(10,20,30)
1
2
3
4
5
6

# 元素集合

let divs = document.querySelectorAll('div');
console.log(Array.from(divs));
1
2

# 类似数组的对象

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};
let arr = Array.from(arrayLike);
console.log(arr);
1
2
3
4
5
6
7
8

# Array.of()

Array.of()方法用于将一组值,转换为数组

Array.of(3, 11, 8) // [3,11,8]
1

实时效果反馈

1. 下列代码输出结果是什么:

Array.of(3)
Array(3)
1
2

A [3] [3]

B [,,,] [,,,]

C [,,] [3]

D [3] [,,,]

答案

1=>D

# 对象的扩展

# 属性的简洁表示法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name = "iwen"
const user = {
    name,
    age:20
}
1
2
3
4
5

除了属性简写,方法也可以简写

const o = {
  method() {
    return "Hello!";
  }
};

// 等同于

const o = {
  method: function() {
    return "Hello!";
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13

这种写法用于函数的返回值,将会非常方便

function getPoint() {
  const x = 1;
  const y = 10;
  return {x, y};
}

getPoint() // {x:1, y:10}
1
2
3
4
5
6
7

# 属性名表达式

ES6 允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内

let propKey = 'itbaizhan';

let obj = {
  [propKey]: true,
  ['a' + 'bc']: 123
};
1
2
3
4
5
6

# 对象的扩展运算符

ES2018 将这个运算符引入了对象

let z = { a: 3, b: 4 };
let n = { ...z };
console.log(n);

{...{}, a: 1}
// { a: 1 }
1
2
3
4
5
6

实时效果反馈

1. 下列代码输出结果是什么:

let propKey = 'itbaizhan';
let obj = {
    [propKey]: true,
    ['a' + 'bc']: 123
};
console.log(obj.propKey);
1
2
3
4
5
6

A true

B 报错

C undefined

D propKey

答案

1=>C

# 函数的扩展_箭头函数

# 基本用法

ES6 允许使用“箭头”(=>)定义函数

var add = (x) => x;

// 等同于
var add = function (x) {
    return x;
};
1
2
3
4
5
6

如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分

var add = (x,y) => x+y;
// 等同于
var add = function (x,y) {
    return x+y;
};

var add = () => 100;
// 等同于
var add = function () {
    return 100;
};
1
2
3
4
5
6
7
8
9
10
11

如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回

var add = (x,y) => {
    var z = 10;
    return x+y+z
};

// 等同于
var add = function (x,y) {
    var z = 100
    return x+y+z
};
1
2
3
4
5
6
7
8
9
10

由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。

var add = (x,y) => ({x:10,y:20});
1

箭头函数的一个用处是简化回调函数(匿名函数)

var arr = [10,20,30]
arr.map(item =>{
    console.log(item);
})
1
2
3
4

# 使用注意点

对于普通函数来说,内部的this指向函数运行时所在的对象,但是这一点对箭头函数不成立。它没有自己的this对象,内部的this就是定义时上层作用域中的this

var name = "itbaizhan"
var user = {
    name:"iwen",
    getName(){
        setTimeout(() =>{
            console.log(this.name); // iwen
        })
    }
}
user.getName()
1
2
3
4
5
6
7
8
9
10

温馨提示

箭头函数里面根本没有自己的this,而是引用外层的this

实时效果反馈

1. 下列代码运行结果是多少:

var name = "itbaizhan"
var user = {
    name:"iwen",
    getName(){
        setTimeout(() =>{
            console.log(this.name);
        })
    }
}
user.getName()
1
2
3
4
5
6
7
8
9
10

A itbaizhan

B iwen

C null

D 报错

答案

1=>B

# Set 数据结构

# 基本用法

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Set本身是一个构造函数,用来生成 Set 数据结构。

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}
// 2 3 5 4
1
2
3
4
5
6
7
8

通过add()方法向 Set 结构加入成员,结果表明 Set 结构不会添加重复的值。

Set函数可以接受一个数组作为参数

const set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
1
2
3

数组去除重复成员的方法

// 去除数组的重复成员
[...new Set(array)]
1
2

字符串去除重复字符

[...new Set('ababbc')].join('')
// "abc"
1
2

向 Set 加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。

var mySet = new Set();
mySet.add("5")
mySet.add(5)
console.log(mySet); // Set(2) {'5', 5}
1
2
3
4

# size属性

返回Set实例的成员总数

const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
1
2

实时效果反馈

1. 下列代码输出结果是多少:

var mySet = new Set();
mySet.add("5")
mySet.add(5)
mySet.add(5)
console.log(mySet); 
1
2
3
4
5

A "5" 5 5

B "5" 5

C "5"

D null

答案

1=>B

# Set 数据结构方法

# add()

set 添加方法

var mySet = new Set();
mySet.add("5")
console.log(mySet); 
1
2
3

# delete()

删除某个值,返回一个布尔值,表示删除是否

var mySet = new Set();
mySet.add("5")
var flag = mySet.delete("5");
console.log(flag);  // true
1
2
3
4

# has()

返回一个布尔值,表示该值是否为Set的成员

var mySet = new Set();
mySet.add("5")
var flag = mySet.has("5");
console.log(flag);  // true
1
2
3
4

# clear()

清除所有成员,没有返回值

var mySet = new Set();
mySet.add("5")
mySet.clear();
console.log(mySet);  // Set(0) {size: 0}
1
2
3
4

实时效果反馈

1. 下列那个方法可以清空Set数据结构中所有的数据:

A add()

B delete()

C has()

D clear()

答案

1=>D

# Promise 对象

# 基本概念

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易

# 基本用法

ES6 规定,Promise对象是一个构造函数,用来生成Promise实例

const promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
1
2
3
4
5
6
7
8
9

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署

Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。

promise.then(function(value) {
  // success
}, function(error) {
  // failure
});
1
2
3
4
5

# 加载图片资源例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div></div>
    <script>
        function loadImageAsync(url) {
            var promise = new Promise(function (resolve, reject) {
                const image = new Image();
                image.onload = function () {
                    resolve(image);
                };
                image.onerror = function () {
                    reject(new Error('Could not load image at ' + url));
                };
                image.src = url;
            });
            return promise;
        }
        loadImageAsync("http://iwenwiki.com/api/vue-data/vue-data-1.png")
        .then(function(data){
            console.log(data);
            $("div").append(data)
        },function(error){
            $("div").html(error)
        })
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

实时效果反馈

1. Promise的作用是什么,下列描述正确的是:

A Promise 是异步编程的一种解决方案,可以将异步操作以同步操作的流程表达出来

B Promise是同步编程的一种解决方案,可以将同步操作以异步操作的流程表达出来

C Promise使得控制同步操作更加容易

D Promise还不是ES6的标准,目前是社区版本

答案

1=>A

# Promise对象_Ajax实操

Promise封装Ajax,让网络请求的异步操作变得更简单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const getJSON = function (url) {
            const promise = new Promise(function (resolve, reject) {
                const handler = function () {
                    if (this.readyState !== 4) {
                        return;
                    }
                    if (this.status === 200) {
                        resolve(this.response);
                    } else {
                        reject(new Error(this.statusText));
                    }
                };
                const client = new XMLHttpRequest();
                client.open("GET", url);
                client.onreadystatechange = handler;
                client.responseType = "json";
                client.setRequestHeader("Accept", "application/json");
                client.send();
            });
            return promise;
        };
        		getJSON("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php").then(function (json) {
            console.log(json);
        }, function (error) {
            console.error('出错了', error);
        });
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# Async 函数

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

async函数可以将异步操作变为同步操作

# 示例代码

function print(){
    setTimeout(() =>{
        console.log("定时器");
    },1000)
    console.log("Hello");
}

print()
1
2
3
4
5
6
7
8

# 基本语法

function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(function() {
            console.log("定时器内容")
            resolve()
        }, ms)
    });
}

// 1. 函数前面使用async标记
async function asyncPrint(ms, value) {
    // 2. 把具有异步操作的代码放入await
    await timeout(ms);
    console.log(value)
}

asyncPrint(1000, "hello")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 异步应用

function ajax(url){
    return new Promise(function(resolve,reject){
        $.getJSON(url,function(result){
            resolve(result)
        },function(error){
            reject(error) 
        })
    })
}

async function getInfo(){
    let ids = await ajax("http://iwenwiki.com/api/generator/list.php")
    let names = await ajax("http://iwenwiki.com/api/generator/id.php?id="+ids[0])
    let infos = await ajax("http://iwenwiki.com/api/generator/name.php?name=" + names.name)
    console.log(infos);
}

getInfo();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

实时效果反馈

1. Async 是什么:

A Async是完成网络请求,如Ajax一样

B Async的作用是完成异步网络请求,如Ajax一样

C Async使得异步操作变得更加方便

D Async是新的网络请求解决方案

答案

1=>C

# Class 的基本语法

# 类的由来

JavaScript 语言中,生成实例对象的传统方法是通过构造函数

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);
1
2
3
4
5
6
7
8
9
10

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类

基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
1
2
3
4
5
6
7
8
9
10

# constructor 方法

constructor()方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor()方法,如果没有显式定义,一个空的constructor()方法会被默认添加

class Point {
}

// 等同于
class Point {
  constructor() {}
}
1
2
3
4
5
6
7

# 类的实例

生成类的实例的写法,与 ES5 完全一样,也是使用new命令

class Point {
  // ...
}

// 报错
var point = Point(2, 3);

// 正确
var point = new Point(2, 3);
1
2
3
4
5
6
7
8
9

# 注意点

# 不存在提升

类不存在变量提升(hoist),这一点与 ES5 完全不同

new Foo(); // ReferenceError
class Foo {}
1
2

实时效果反馈

1. 下列代码,划横线处要填写的代码时:

class Person {
    constructor(name) {
        this.name = name;
    }
}

var p = ___ Person("sxt")
1
2
3
4
5
6
7

A ""

B new

C this

D class

答案

1=>B

# Class属性与方法

# 实例方法

通过类的实例对象调用方法

class People{
    say(){
        console.log("Hello");
    }
}
var p = new People();
p.say()
1
2
3
4
5
6
7

# 实例属性

实例属性指的是类的实例对象可调用的属性

class People{
    constructor(name,age){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log(this.name,this.age);
    }
}
var p = new People("iwen",20);
p.say()
console.log(p.name,p.age);
1
2
3
4
5
6
7
8
9
10
11
12

# 静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”

class Person {
    static classMethod() {
        console.log("Hello");
    }
}

Person.classMethod() // Hello

var p = new Person();
p.classMethod() // p.classMethod is not a function
1
2
3
4
5
6
7
8
9
10

温馨提示

注意,如果静态方法包含this关键字,这个this指的是类,而不是实例。

class People {
    static getSay() {
        this.say();
    }
    static say() {
        console.log('hello');
    }
    say() {
        console.log('world');
    }
}
People.getSay() // hello
1
2
3
4
5
6
7
8
9
10
11
12

# 静态属性

静态属性指的是 Class 本身的属性,即Class.propName

class People{}
People.status = "等待"
console.log(People.status);
1
2
3

实时效果反馈

1. 下列代码,运行结果是什么:

class People {
    static getSay() {
        this.say();
    }
    static say() {
        console.log('hello');
    }
    say() {
        console.log('world');
    }
}
People.getSay()
1
2
3
4
5
6
7
8
9
10
11
12

A hello

B world

C null

D undefined

答案

1=>A

# Class 的继承

# 基础用法

Class 可以通过extends关键字实现继承,让子类继承父类的属性和方法。extends 的写法比 ES5 的原型链继承,要清晰和方便很多

class Point {
}

class ColorPoint extends Point {
}
1
2
3
4
5

ES6 规定,子类必须在constructor()方法中调用super(),否则就会报错,这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,添加子类自己的实例属性和方法。如果不调用super()方法,子类就得不到自己的this对象

class Point {
    constructor(x,y){
        this.x = x;
        this.y = y;
    }
    getPoint(){
        console.log(this.x,this.y);
    }
}
class ColorPoint extends Point {
    constructor(x,y,z){
        super(x,y)
        this.z = z;
    }
}
let cp = new ColorPoint(10,20,30)
cp.getPoint();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# Module 的语法

历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。其他语言都有这项功能,比如 Ruby 的require、Python 的import,甚至就连 CSS 都有@import,但是 JavaScript 任何这方面的支持都没有,这对开发大型的、复杂的项目形成了巨大障碍

ES6 模块是通过export命令显式指定输出的代码,再通过import命令输入。

export var Hello = "hello" // hello.js文件
import { Hello } from "./hello.js" // index.js文件
1
2

# 测试方式

我们采用Nodejs方式进行测试Module语法

但是nodejs采用的是CommonJS的模块化规范,使用require引入模块;而import是ES6的模块化规范关键字。想要使用import,必须引入babel转义支持,通过babel进行编译,使其变成node的模块化代码。

疑惑:为啥不用前端方式测试,前端方式测试会更加麻烦

第一步:全局安装babel-cli npm install -g babel-cli

第二步:安装 babel-preset-env npm install -D babel-preset-env

第三步:运行代码 babel-node --presets env index.js

# export 命令

export命令导出变量

export var firstName = 'sxt';
export var lastName = 'itbaizhan';
export var year = 2000;
1
2
3

export命令导出函数

export function add(x, y) {
  return x + y;
};
1
2
3

# import 命令

使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块

// name.js
export var firstName = 'sxt';
export var lastName = 'itbaizhan';
export var year = 2000;

// main.js
import { firstName, lastName, year } from './profile.js';
1
2
3
4
5
6
7

如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名

// value.js
export var value = 1;

// main.js
import { value as val } from './value.js';
1
2
3
4
5

除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面

// circle.js
export function area(radius) {
  return Math.PI * radius * radius;
}
export function circumference(radius) {
  return 2 * Math.PI * radius;
}


// main.js
import { area, circumference } from './circle';
// 可以修改如下
import * as circle from './circle';
1
2
3
4
5
6
7
8
9
10
11
12
13

# export default 命令

从前面的例子可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

// export-default.js
export default function () {
  console.log('foo');
}
1
2
3
4

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字

// import-default.js
import customName from './export-default';
customName(); // 'foo'
1
2
3

实时效果反馈

1. 下列那个不属于ES6的Module语法的关键字:

A export

B import

C export default

D require

答案

1=>D

#html#web
上次更新: 2024/04/21, 09:42:22
JavaScript 对象
Vue 快速上手

← JavaScript 对象 Vue 快速上手→

最近更新
01
微信支付功能的实现与流程
11-21
02
购物车与结算区域的深入优化与功能完善
11-21
03
购物车与结算区域的功能实现与优化
11-21
更多文章>
Theme by Vdoing | Copyright © 2023-2024 EmmmuaCode | 黔ICP备2022009864号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式