什么是 ECMAScript?
ECMAScript 是由 Ecma 国际通过 ECMA-262 标准化的脚本程序设计语言。
什么是 ECMA-262 ?
Ecma
国际制定了许多标准,而
ECMA-262
只是其中的一个,所有标准列表查看
http://www.ecma-international.org/publications/standards/Standard.htm
ECMA-262 历史
ECMA-262
(
ECMAScript
)历史版本查看网址
http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm
![](https://i-blog.csdnimg.cn/blog_migrate/caa635d10da984cf6b4901124ee179c5.png)
![](https://i-blog.csdnimg.cn/blog_migrate/fef7b2180b34d992b5a7c6633de22701.png)
注:从
ES6
开始,每年发布一个版本,版本号比年份最后一位大
1
为什么要学习 ES6
ES6
的版本变动内容最多,具有里程碑意义
ES6
加入许多新的语法特性,编程实现更简单、高效
ES6
是前端发展趋势,就业必备技能
ECMASript 6 新特性
let 关键字
let
关键字用来声明变量,使用
let
声明的变量有几个特点:
1)
不允许重复声明
2)
块儿级作用域
3)
不存在变量提升
4)
不影响作用域链
应用场景:以后声明变量使用
let
就对了
const
关键字
const
关键字用来声明常量,
const
声明有以下特点
1)
声明必须赋初始值
2)
标识符一般为大写
3)
不允许重复声明
4)
值不允许修改
5)
块儿级作用域
注意
:
对象属性修改和数组元素变化不会出发
const
错误
应用场景:声明对象类型使用
const
,非对象类型声明选择
let
变量的解构赋值
ES6
允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称
为解构赋值
<script>
//复杂解构
let wangfei = {
name: '王菲',
age: 18,
songs: ['红豆', '流年', '暧昧', '传奇'],
history: [
{ name: '窦唯' },
{ name: '李亚鹏' },
{ name: '谢霆锋' }
]
};
const { name, age, songs: [one, two, three], history: [first, second, third] } = wangfei
console.log(one, two, three);
console.log(first, second, third);
</script>
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串
模板字符串(
template string
)是增强版的字符串,用反引号(
`
)标识,特点:
1)
字符串中可以出现换行符
2)
可以使用
${xxx}
形式输出变量
<script>
// ``
let str = `字符串`
console.log(typeof str);
// 使用变量
let name = '张三'
str = `我的姓名是:${name}`
console.log(str);
</script>
简化对象写法
ES6
允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这
样的书写更加简洁。
<script>
let name = '张三', age = 18
const sayHi = function () {
console.log(`${name} 说我今年${age}岁`);
}
// const obj = {
// name:name,
// age:age,
// sayHi:sayHi
// }
// 当key和value名称一致,就可以只写一个
const obj = {
name,
age,
sayHi,
sprak(a){
console.log(a);
}
}
console.log(obj);
obj.sprak(1)
</script>
箭头函数
ES6 允许使用「箭头」(=>)定义函数。
箭头函数的注意点
:
1)
如果形参只有一个,则小括号可以省略
2)
函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的
执行结果
3)
箭头函数
this
指向声明时所在作用域下
this
的值
4)
箭头函数不能作为构造函数实例化
5)
不能使用
arguments
箭头函数的基本写法
<script>
// 普通函数
// const foo = function(a,b){
// console.log(a,b);
// }
// foo(1,2)
// // 箭头函数 =>
const foo = (a,b)=> {
console.log(a,b);
}
foo(1,2)
</script>
箭头函数变形-参数
<script>
// 无参数()必须写
const foo = () => {
console.log('无参数,括号必须写');
}
// 当参数只有一个的时候,括号可以省略
const foo1 = a => {
console.log('参数只有一个的时候,括号可以省略');
}
// 当有多个参数的时候,括号必须写
const foo2 = (a, b, c) => {
console.log('参数多个的时候,括号必须加');
}
</script>
箭头函数变形-方法体
<script>
// 当方法体有多行代码时,大括号必须写
const foo = n => {
let a = 10
let b = 20
}
// 当方法体只有一行代码的时候,大括号可以省略
const foo1 = a => console.log(a)
foo1(500)
// 当方法体只有一行代码,且为返回值的时候,如果大括号省略,return必须省略
const foo2 = a => a
console.log(foo2(5));
// 箭头函数的出现并不是为了替代function
// const foo3 = ()=>{
// console.log(arguments);
// }
// foo3(1,2,3,4,5,6)
</script>
箭头函数的this指向问题
<script>
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayHi = function(){
console.log(this); // 实例化对象
// setTimeout(function(){
// console.log(this); // window
// },1000)
setTimeout(()=>{
console.log(this); // 箭头函数的this永远指向我外部的this,自身没有this指向
},1000)
}
new Person('张三',18).sayHi()
</script>
注意:箭头函数不会更改
this
指向,用来指定回调函数会非常合适
rest
参数
ES6
引入
rest
参数,用于获取函数的实参,用来代替
arguments
<script>
// ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
// 这里的 ...将参数列表合并为一个数组
const foo = (...args)=>{
console.log(args);
}
foo(2,6,7,8,9,50)
const foo1 = (a,b,...args)=>{
console.log(args);
}
foo1(2,6,7,8,9,50)
</script>
spread
扩展运算符
扩展运算符(
spread
)也是三个点(
...
)。它好比
rest
参数的逆运算,将一
个数组转为用逗号分隔的参数序列,对数组进行解包。
<script>
// spread 运算符又称三点运算符
// 将一个数组展开
let tfboys = ['德玛西亚之力', '德玛西亚之翼', '德玛西亚皇子'];
function fn() {
//伪数组
console.log(arguments);
}
// ... 展开数组 fn('德玛西亚之力','德玛西亚之翼','德玛西亚皇子')
fn(...tfboys)
// arr = [1,2,3,4,5,6,'德玛西亚之力','德玛西亚之翼','德玛西亚皇子']
let arr = [1, 2, 3, 4, 5, 6, ...tfboys]
arr.push(...tfboys)
console.log(arr);
// 展开对象
let skillOne = {
q: '致命打击',
};
let skillTwo = {
w: '勇气'
};
let skillThree = {
e: '审判'
};
let skillFour = {
r: '德玛西亚正义'
};
const gailun = {...skillOne,...skillTwo,...skillThree,...skillFour}
console.log(gailun);
</script>
Symbol
基本使用
ES6
引入了一种新的原始数据类型
Symbol
, 表示独一无二的值。它是
JavaScript
语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol
特点
1)
Symbol
的值是唯一的,用来解决命名冲突的问题
2)
Symbol
值不能与其他数据进行运算
3)
Symbol
定义的对象属性不能使用
for…in
循环遍历, 但是可以使用
Reflect.ownKeys
来获取对象的所有键名
<script>
// 创建
const s1 = Symbol()
console.log(typeof s1);
// 唯一:引用地址不同、值也不同
const s2 = Symbol('网星软件')
const _s2 = Symbol('网星软件')
console.log(s2 === _s2);
// 使用 Symbol for 定义的指向统一内存地址,值一样
let s3 = Symbol.for('网星软件');
let _s3 = Symbol.for('网星软件');
console.log(s3 === _s3);
const obj = {
sex: '男',
name: 'zhangSAN'
}
obj[s2] = 'symbol'
const sy = Symbol('name')
const _sy = Symbol('name')
obj[sy] = "xiaosan"
obj[_sy] = "sansan"
console.log(obj);
class Person { }
let p1 = new Person();
console.log(p1 instanceof Person); //true
// instanceof 和 [Symbol.hasInstance] 是等价的
console.log(Person[Symbol.hasInstance](p1)) // true
console.log({} instanceof Object);
// Object {}
console.log(Object[Symbol.hasInstance]({}));
const arr = [1, 2, 3, 4, 5, 6]
const arr2 = [1, 2, 3, 4, 5, 6]
arr2[Symbol.isConcatSpreadable] = false
console.log(arr.concat(arr2));
console.log({}[Symbol.iterator] === undefined);
(async function foo() {
for await (const item of arr) {
console.log(item);
}
})()
console.log(11111);
const regexp1 = /foo/
//Symbol.match 置为 false,使用 match 属性的表达式检查会认为该象不是正则表达式对象。startsWith 和 endsWith 方法将不会抛出 TypeError
regexp1[Symbol.match] = false;
console.log('/foo/'.startsWith(regexp1));
console.log('/baz/'.endsWith(regexp1));
const object ={
name:'张三'
}
object[Symbol.unscopables] ={
name:false
}
with(object){
console.log(name);
}
</script>
for-of的使用
遍历器(
Iterator
)就是一种机制。它是一种接口,为各种不同的数据结构提
供统一的访问机制。任何数据结构只要部署
Iterator
接口,就可以完成遍历操作。
1)
ES6
创造了一种新的遍历命令
for...of
循环,
Iterator
接口主要供
for...of
消费
2)
原生具备
iterator
接口的数据
(
可用
for of
遍历
)
a)
Array
b)
Arguments
c)
Set
d)
Map
e)
String
f)
TypedArray
g)
NodeList
3)
工作原理
a)
创建一个指针对象,指向当前数据结构的起始位置
b)
第一次调用对象的
next
方法,指针自动指向数据结构的第一个成员
c)
接下来不断调用
next
方法,指针一直往后移动,直到指向最后一个成员
d)
每调用
next
方法返回一个包含
value
和
done
属性的对象
注
:
需要自定义遍历数据的时候,要想到迭代器。
<script>
const arr = [1,2,5,6]
for (const item of arr) {
console.log(item);
}
</script>
生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
1)
*
的位置没有限制
2)
生成器函数返回的结果是迭代器对象,调用迭代器对象的
next
方法可以得到
yield
语句后的值
3)
yield
相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次
next
方法,执行一段代码
4)
next
方法可以传递实参,作为
yield
语句的返回值
<script>
function* gen() {
yield '一只没有耳朵'
yield '一只没有尾巴'
return '真奇怪'
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
</script>
Promise
https://www.jianshu.com/p/1b63a13c2701
Promise
是
ES6
引入的异步编程的新解决方案。语法上
Promise
是一个构造函数,
用来封装异步操作并可以获取其成功或失败的结果。
1)
Promise
构造函数
: Promise (excutor) {}
2)
Promise.prototype.then
方法
3)
Promise.prototype.catch
方法
<script>
// Promise 类
// 在使用Promise的时候需要传参,参数一个函数fn
// fn 又会有两个形参,resolve,reject
// resolve,reject 这两个又是两个函数,就是回调函数
// resolve 表示成功的回调 结果会传到then
// reject 表示失败的回调 结果会传到catch
// const p = new Promise((resolve, reject) => {
// let a = 12
// if (a == 10) {
// resolve(a)
// } else {
// reject(a)
// }
// }).then(res => {
// console.log('成功的a=' + res);
// }).catch(err => {
// console.log(err);
// })
const p = new Promise((resolve, reject) => {
let a = 12
if (a == 10) {
resolve(a)
} else {
reject(a)
}
})
p.then(res => {
console.log('成功的a=' + res);
}).catch(err => {
console.log(err);
})
</script>
<script>
const p = new Promise((resolve, reject) => {
let a = 10
if (a == 10) {
a += 2
resolve(a)
} else {
reject(a)
}
})
p.then(res => {
return new Promise((resolve, reject) => {
if (res == 12) {
resolve(res)
}
})
}).catch(err => {
console.log(err);
}).then(res => {
console.log(res);
})
// 回调地狱
// 第一次请求
// $.ajax({
// url: '',
// data: {},
// success(res) {
// // 第二次请求需要第一次请求的响应的数据
// $.ajax({
// url: '',
// data: {},
// success(res) {
// // 第三次请求需要第二次请求的响应的数据
// $.ajax({
// url: '',
// data: {},
// success(res) {
// // 第三次请求需要第二次请求的响应的数据
// $.ajax({
// url: '',
// data: {},
// success(res) {
// // 第三次请求需要第二次请求的响应的数据
// }
// })
// }
// })
// }
// })
// }
// })
</script>