ES6教程
ECMA(European Computer Manufacturers Association),中文名称为欧洲计算机制造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。
ECMAScript 是由ECMA国际通过 ECMA-262 标准化的脚本程序设计语言。
ES6
let
ES5中声明变量使用关键字var,但是在ES6中声明变量都使用关键字let。
-
变量不能重复声明。
<script type="text/javascript"> var a=1; var a=2; console.log(a); </script>
<script type="text/javascript"> let a=1; let a=2; console.log(a); </script>
-
块级作用域。
<script type="text/javascript"> { var a=1; } console.log(a); </script>
<script type="text/javascript"> { let a=1; } console.log(a); </script>
-
不存在变量提升。
<script type="text/javascript"> console.log(a); var a=10; </script>
<script type="text/javascript"> console.log(a); let a=10; </script>
-
不影响作用域链。
<script type="text/javascript"> var a=5 function fn(){ console.log(a) } fn() </script>
<script type="text/javascript"> let a=5 function fn(){ console.log(a) } fn() </script>
应用场景:以后声明变量使用 let 就对了!
const
使用const声明的变量表示是常量。
-
一定要赋初始值。
<script type="text/javascript"> const PI console.log(PI) </script>
-
一般常量使用大写。
<script type="text/javascript"> const PI=3.141516 console.log(PI) </script>
-
不允许重复声明。
<script type="text/javascript"> const ARR=1 const ARR=2 console.log(ARR) </script>
-
常量的值不能够修改。
<script type="text/javascript"> const PI=3.141516 PI=2 console.log(PI) </script>
-
块级作用域。
<script type="text/javascript"> { const PI=3.141516 } console.log(PI) </script>
-
对常量数组和对象,由于变量名对应的内存中存储的是数组或者对象的地址,所以如果更改对象或者数组的内容,其实是可以的,因为其地址并未改变,故不违背常量值不能改变这一点。
<script type="text/javascript"> const ARR=[1,2,3,4,5] console.log(ARR) ARR.push(6) console.log(ARR) </script>
注意: 对象属性修改和数组元素变化不会出发 const 错误!
应用场景:声明对象类型使用 const,非对象类型声明选择 let!
解构赋值
解构赋值,表示允许按照一定模式从数组和对象中提取值,从而对变量进行赋值。
-
对数组进行解构赋值。
//数组的解构赋值 const arr = ['张学友', '刘德华', '黎明', '郭富城']; let [zhang, liu, li, guo] = arr; console.log(zhang); console.log(liu); console.log(li); console.log(guo);
-
对对象进行解构赋值。
//对象的解构赋值 const lin = { name: '林志颖', tags: ['车手', '歌手', '小旋风', '演员'] }; let {name, tags} = lin; console.log(name); console.log(tags);
-
对嵌套进行解构赋值。
<script type="text/javascript"> //复杂解构 let wangfei = { name: '王菲', age: 18, songs: ['红豆', '流年', '暧昧', '传奇'], history: [ {name: '窦唯'}, {name: '李亚鹏'}, {name: '谢霆锋'} ] }; let {songs: [one, two, three], history: [first, second, third]} = wangfei; console.log(one); console.log(two); console.log(three); console.log(first); console.log(second); console.log(third); // 注意下面两种是错误的奥! console.log(songs); console.log(history); </script>
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式!
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
-
字符串中可以出现换行符。
// 定义字符串 let str = `<ul> <li>沈腾</li> <li>玛丽</li> <li>魏翔</li> <li>艾伦</li> </ul>`; console.log(str)
-
可以使用 ${xxx} 形式输出变量。
<script type="text/javascript"> // 变量拼接 let star = '王宁'; let result = `${star}在前几年离开了开心麻花`; console.log(result) </script>
注意:当遇到字符串与变量拼接的情况使用模板字符串!
简化对象
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
如果是直接在对象里面写函数,那么直接省略:function即可!
```
<script type="text/javascript">
let name = '尚硅谷';
let slogon = '永远追求行业更高标准';
let improve = function () {
console.log('可以提高你的技能');
}
//属性和方法简写
let atguigu = {
name,
slogon,
improve,
change() {
console.log('可以改变你')
}
};
</script>
```
注意:对象简写形式简化了代码,所以以后用简写就对了!
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
-
通用写法。
let fn = (arg1, arg2, arg3) => { return arg1 + arg2 + arg3; }
注意事项:
-
箭头函数的this是静态的,也就是说箭头函数没有自己的this,其this是指向函数声明时所在作用域下的this的值。
-
箭头函数不能够作为构造函数。
-
箭头函数不能使用arguments变量。
<script type="text/javascript"> let fn4 = () => { console.log(this); } fn4() </script>
<script type="text/javascript"> let school = { name: '尚硅谷', getName(){ let fn5 = () => { console.log(this); } fn5(); } }; // 箭头函数的this指向的是getName()的this 而getName()是由对象school调用 故this指向的是school对象 school.getName(); </script>
-
-
简化写法。
注意事项:
- 省略():当形参只有一个的时候。
let fn2 = num => { return num * 10; };
- 省略{}:当代码只有一句的时候。此时return也必须省略。
let fn3 = score => score * 20;
- 省略():当形参只有一个的时候。
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适!
rest参数
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments。
注意!rest参数是在形参地方用!!
-
作用与 arguments 类似。
function add(...args){ console.log(args); } add(1,2,3,4,5);
-
rest 参数必须是最后一个形参。
function minus(a,b,...args){ console.log(a,b,args); } minus(100,1,2,3,4,5,19);
注意:rest 参数非常适合不定个数参数函数的场景!
spread 扩展运算符
扩展运算符(spread)也是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。
注意!spread 扩展运算符是在实参地方用!!
-
展开数组。
<script type="text/javascript"> let tfboys = ['德玛西亚之力','德玛西亚之翼','德玛西亚皇子']; function fn(){ console.log(arguments); } fn(...tfboys) </script>
-
展开对象。
<script type="text/javascript"> let skillOne = { q: '致命打击', }; let skillTwo = { w: '勇气' }; let skillThree = { e: '审判' }; let skillFour = { r: '德玛西亚正义' }; let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour}; console.log(gailun) </script>
注意:spread 扩展运算符可以用来进行数组合并、数组克隆以及将伪数组变成真数组!
Symbol
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。
- Symbol 的值是唯一的,用来解决命名冲突的问题。
- Symbol 值不能与其他数据进行运算。
创建Symbol:
-
单纯的symbol()。
<script type="text/javascript"> let s1 = Symbol(); console.log(s1, typeof s1); </script>
-
添加标识的symbol()。
let s2 = Symbol('尚硅谷'); let s2_2 = Symbol('尚硅谷'); console.log(s2 === s2_2);
-
使用Symbol.for()。
<script type="text/javascript"> let s3 = Symbol.for('尚硅谷'); let s3_2 = Symbol.for('尚硅谷'); console.log(s3) console.log(s3_2) console.log(s3 === s3_2); </script>
有时候我们就是希望传递相同的参数就能够创建出相同的Symbol值来使用。Symbol为我们提供了一个方法:Symbol.for(),它接收一个字符串作为参数(可选),然后会在全局中搜索有没有以该参数作为描述的Symbol值,如果有则直接返回该Symbol,否则将以该参数作为描述创建一个新的Symbol值,并将其注册的全局环境供搜索,用Symbol方法创建的Symbol值是不会注册到全局的。
也就是说在使用Symbol.for()创建Symbol值时,首先会到全局环境中检测有没有创建,有就直接返回,没有再去创建新值,而Symbol则不管有没有都是创建新值。
另外:Symbol.for()在创建Symbol值时是登记在全局环境中的,不管有没有在全局环境运行。
Symbol一般应用到向对象中添加方法,由于你一开始不知道想添加进去的属性名是否在对象中已经存在,所以需要先去判断,如果没有才能添加,这样就增加了负担,由于symbol是创建唯一的值,故可以自定义symbol,然后给对象添加方法奥!
注: 遇到唯一性的场景时要想到 Symbol!
迭代器
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费。
注:需要自定义遍历数据的时候,就想到迭代器!
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
-
生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到
yield 语句后的值。 -
yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next
方法,执行一段代码。 -
next 方法可以传递实参,作为 yield 语句的返回值。
<script type="text/javascript"> // 注意*一定要加上奥! function * gen(){ yield '一只没有耳朵'; yield '一只没有尾巴'; yield '真奇怪'; } let iterator = gen(); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); </script>
注:异步编程想想生成器!
Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,
用来封装异步操作并可以获取其成功或失败的结果。
- Promise构造函数的参数是一个函数,该函数又有两个形参,一般是resolve(表示成功)和reject(表示失败)。
- Promise构造函数的实例化对象可以调用then方法,其有两个函数参数,一个表示如果成功时的处理,其函数形参一般是value,一个表示如果失败时的处理,其函数形参一般是reason。
- Promise构造函数的实例化对象可以调用catch方法,其表示如果失败的话怎么处理,相当于一个语法糖。
- Promise构造函数的实例化对象调用then方法后的返回对象仍然是一个Promise对象,其状态取决于回调函数的返回结果,如果是返回非Promise对象或者是返回失败状态的Promise对象,其结果均是Promise对象,如果抛出错误,那就是异常啦,区别在于status和value的取值。
注:异步编程想想Promise!
Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的。
集合的属性和方法:
-
size 返回集合的元素个数。
-
add 增加一个新元素,返回当前集合。
-
delete 删除元素,返回 boolean 值。
-
has 检测集合中是否包含某个元素,返回 boolean 值。
-
clear 清空集合,返回 undefined。
<script type="text/javascript"> //创建一个空集合 let s = new Set(); console.log(s); //创建一个非空集合 let s1 = new Set([1,2,3,1,2,3]); console.log(s1); //集合属性与方法 //返回集合的元素个数 console.log(s1.size); //添加新元素 console.log(s1.add(4)); //删除元素 console.log(s1.delete(1)); //检测是否存在某个值 console.log(s1.has(2)); //清空集合 console.log(s1.clear()); </script>
Set可以很好的去进行数组去重和交集并集差集运算奥!
注:数组去重和交集并集差集运算想一想Set!
Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map 的属性和方法:
-
size 返回 Map 的元素个数。
-
set 增加一个新元素,返回当前 Map。
-
get 返回键名对象的键值。
-
has 检测 Map 中是否包含某个元素,返回 boolean 值。
-
clear 清空集合,返回 undefined。
<script type="text/javascript"> //创建一个空 map let m = new Map(); console.log(m); //创建一个非空 map let m2 = new Map([ ['name','尚硅谷'], ['slogon','不断提高行业标准'] ]); console.log(m2); //属性和方法 //获取映射元素的个数 console.log(m2.size); //添加映射值 console.log(m2.set('age', 6)); //获取映射值 console.log(m2.get('age')); //检测是否有该映射 console.log(m2.has('age')); //清除 console.log(m2.clear()); </script>
注:当对象的属性名不是字符串的时候想一想Map!
Class
ES5中没有类的概念,其使用的是构造函数,通过构造函数来实例化对象,然后构造函数的继承关系是使用原型属性设置的。
ES6中引入了关键字Class来定义类,然后使用extends关键字来表示类的继承关系。
注意事项:
- class 声明类。
- constructor 定义构造函数初始化。
- extends 继承父类。
- super 调用父级构造方法。
- static 定义静态方法和属性。
- 父类方法可以重写。
类中的方法要是函数简写奥!
<script type="text/javascript">
//父类
class Phone {
//构造方法
constructor(brand, color, price) {
this.brand = brand;
this.color = color;
this.price = price;
}
//对象方法
call() {
console.log('我可以打电话!!!')
} }
//子类
class SmartPhone extends Phone {
constructor(brand, color, price, screen, pixel) {
super(brand, color, price);
this.screen = screen;
this.pixel = pixel;
}
//子类方法
photo(){
console.log('我可以拍照!!');
}
playGame(){
console.log('我可以玩游戏!!');
}
//方法重写
call(){
console.log('我可以进行视频通话!!');
}
//静态方法
static run(){
console.log('我可以运行程序')
}
static connect(){
console.log('我可以建立连接')
} }
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088,
'4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();
</script>
class中还有get和set来设置属性!
注:当要使用类的时候想一想Class!
数值扩展
ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。
对象扩展
ES6 新增了一些 Object 对象的方法:
setPrototypeOf 可以直接设置对象的原型!
模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
- 防止命名冲突。
- 代码复用。
- 高维护性。
模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口。
- import 命令用于输入其他模块提供的功能。
导出方式有三种:
-
分别暴露。
-
统一暴露。
-
默认暴露。
引入方式有三种:
-
通用引入。
-
解构引入。
-
简便引入。(针对默认才行)
!!!ES6新特性更完!!!
ES7
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值。
在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同。
ES8
async和await
async 和 await 两种语法结合可以让异步代码像同步代码一样。
async:
- async 函数的返回值为 promise 对象。
- promise 对象的结果由 async 函数执行的返回值决定。
await:
- await 必须写在 async 函数中。
- await 右侧的表达式一般为 promise 对象。
- await 返回的是 promise 成功的值。
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理。
其他
- Object.values()方法返回一个给定对象的所有可枚举属性值的数组。
- Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组。
- Object.getOwnPropertyDescriptors方法返回指定对象所有自身属性的描述对象。
ES9
Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符。
<script type="text/javascript">
function connect({host, port, ...user}) {
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
</script>
ES10
ES11
注意:主要还是ES6啦!!然后就是ES8的async 和 await 啦!!
下一步就是学node.js啦!!