ES6语法
ES6 语法
ECMAScript 6.0(以下简称 ES6,ECMAScript 是一种由 Ecma 国际(前身为欧洲计算机制造商 协会,英文名称是 European Computer Manufacturers Association)通过 ECMA-262 标准化的脚本 程序设计语言)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了,并且 从 ECMAScript 6 开始,开始采用年号来做版本。即 ECMAScript 2015, 就是 ECMAScript6。 它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。 每年一个新版本。
什么是 ECMAScript
来看下前端的发展历程:
- web1.0 时代: 最初的网页以 HTML 为主,是纯静态的网页。网页是只读的,信息流只能从服务的到客户端 单向流通。开发人员也只关心页面的样式和内容即可。
- 1995 年,网景工程师 Brendan Eich 花了 10 天时间设计了 JavaScript 语言。
- web2.0 时代:
1996 年,微软发布了 JScript,其实是 JavaScript 的逆向工程实现。
1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组 织 ECMA,希望这种语言能够成为国际标准。
1997 年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的 标准, 并将这种语言称为 ECMAScript, 这个版本就是 1.0 版。 JavaScript 和 JScript 都是
ECMAScript
的标准实现者,随后各大浏览器厂商纷纷实现了ECMAScript
标准。
所以,ECMAScript 是浏览器脚本语言的规范,而各种我们熟知的 js 语言,如 JavaScript 则是规范的具体实现。
ES6新特性
1.let/var
let | var |
---|---|
let 声明的变量有严格局部作用域 | var 声明的变量往往会越域 |
let 只能声明一次 | var 可以声明多次 |
let 不存在变量提升 | var 会变量提升 |
// var 声明的变量往往会越域
// let 声明的变量有严格局部作用域 {
var a = 1;
let b = 2;
}
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
// var 可以声明多次
// let 只能声明一次
var m = 1
var m = 2
let n = 3
// let n = 4
console.log(m) // 2
console.log(n)// Identifier 'n' has already been declared
// var 会变量提升
// let 不存在变量提升
console.log(x); // undefined
var x = 10;
console.log(y); //ReferenceError: y is not defined
let y = 20;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
JS 中使用 var 来声明一个变量时, 变量的作用域主要是和函数的定义有关
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script>
// 1.没有块级作用域引起的问题: for的块级
// 为什么闭包可以解决问题: 函数是一个作用域.
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
// 1.情况一: ES5中没有使用闭包(错误的方式)
i = 2
{
// i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
// i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
// 2.情况二: ES5中使用闭包
var btns = document.getElementsByTagName('button')
for (var i = 0; i < btns.length; i++) {
;(function (i) {
// 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
})(i)
}
i = 100000000(
(function (i) {
// i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
})(0)
)(
(function (i) {
// i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
})(1)
)(
(function (i) {
// i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
})(2)
)
// ES6中的let
const btns = document.getElementsByTagName('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
i = 10000000
{
i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
{
i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击')
})
}
</script>
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
2.const
建议: 在 ES6 开发中,优先使用 const, 只有需要改变某一个标识符的时候才使用 let.
- 声明之后不允许改变
- 一但声明必须初始化,否则会报错
<script>
// 1.注意一: 一旦给const修饰的标识符被赋值之后, 不能修改
// const name = 'why';
// name = 'abc'; //错误 不可修改
// 2.注意二: 在使用const定义标识符,必须进行赋值
// const name; //错误
// 3.注意三: 常量的含义是指向的对象不能修改, 但是可以改变对象内部的属性.
const obj = {
name: 'why',
age: 18,
height: 1.88,
}
// obj = {}
console.log(obj)
obj.name = 'kobe'
obj.age = 40
obj.height = 1.87
console.log(obj)
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
3.对象增强写法
<script>
// const obj = new Object()
//1.普通写法
// const obj = {
// name: 'why',
// age: 18,
// run: function () {
// console.log('在奔跑');
// },
// eat: function () {
// console.log('在次东西');
// }
// }
//增强写法
// 1.属性的增强写法
const name = 'why'
const age = 18
const height = 1.88
// ES5的写法
// const obj = {
// name: name,
// age: age,
// height: height
// }
// ES6的写法
// const obj = {
// name,
// age,
// height,
// }
//
// console.log(obj);
// 2.函数的增强写法
// ES5的写法
// const obj = {
// run: function () {
//
// },
// eat: function () {
//
// }
// }
//ES6的写法
const obj = {
run() {},
eat() {},
}
</script>
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
40
41
42
43
44
45
46
47
48
49
50
51
4.解构表达式
数组解构
let arr = [1,2,3];
//以前我们想获取其中的值,只能通过角标。ES6 可以这样:
const [x,y,z] = arr;// x,y,z 将与 arr 中的每个位置对应来取值 // 然后打印
console.log(x,y,z);
2
3
4
对象解构
const person = {
name: "jack",
age: 21,
language: [ 'java ', 'js ', 'css ']
}
// 解构表达式获取值,将 person 里面每一个属性和左边对应赋值
const { name, age, language } = person;
// 等价于下面
// const name = person.name;
// const age = person.age;
// const language = person.language;
// 可以分别打印
console.log(name);
console.log(age);
console.log(language);
//扩展:如果想要将 name 的值赋值给其他变量,可以如下,nn 是新的变量名
const { name: nn, age, language } = person;
console.log(nn);
console.log(age);
console.log(language);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
5.字符串扩展
新的API
ES6 为字符串扩展了几个新的 API:
includes()
:返回布尔值,表示是否找到了参数字符串。startsWith()
:返回布尔值,表示参数字符串是否在原字符串的头部。endsWith()
:返回布尔值,表示参数字符串是否在原字符串的尾部。
let str = "hello.vue";
console.log(str.startsWith("hello"));//true
console.log(str.endsWith(".vue"));//true
console.log(str.includes("e"));//true
console.log(str.includes("hello"));//true
2
3
4
5
6.函数优化
函数参数默认值
//在 ES6 以前,我们无法给一个函数参数设置默认值,只能采用变通写法:
function add(a, b) {
// 判断 b 是否为空,为空就给默认值 1
b = b || 1;
return a + b;
}
// 传一个参数
console.log(add(10));
//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值
function add2(a , b = 1) {
return a + b;
}
// 传一个参数
console.log(add2(10));
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
不定参数
不定参数用来表示不确定参数个数,形如,...变量名, 由...加上一个具名参数标识符组成。 具名参数只能放在参数列表的最后,并且有且只有一个不定参数
function fun(...values) {
console.log(values.length)
}
fun(1, 2) //2
fun(1, 2, 3, 4) //4
2
3
4
5
箭头函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
// 1.参数问题:
// 1.1.放入两个参数
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
// 1.2.放入一个参数
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
//1.3 空参数
var f = () => 5;
// 等同于
var f = function () { return 5 };
//1.4 函数体中多条语句,使用return语句返回并使用大括号将函数体包围起来
var sum = (num1, num2) => {
num1+=1;
return num1 + num2; }
//1.5 函数结构体也可以不返回
//一 单行不返回使用void关键字标识
let fn = () => void doesNotReturn();
// 二 多行语句不使用return
var sum = (num1, num2) => {
num1+=1;
num1 + num2; }
//1.6 如果箭头函数直接返回一个对象,由于大括号被解释为代码块,必须在对象外面加上括号,否则会报错。
// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });
// 2.函数中
// 2.1.函数代码块中有多行代码时
const test = () => {
// 1.打印Hello World
console.log('Hello World');
// 2.打印Hello Vuejs
console.log('Hello Vuejs');
}
// 2.2.函数代码块中只有一行代码
// const mul = (num1, num2) => {
// return num1 + num2
// }
const mul = (num1, num2) => num1 * num2
console.log(mul(20, 30));
// const demo = () => {
// console.log('Hello Demo');
// }
const demo = () => console.log('Hello Demo')
console.log(demo());
</script>
</body>
</html>
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
7.对象优化
新增的API
ES6 给 Object 拓展了许多新的方法,如:
keys(obj)
:获取对象的所有 key 形成的数组values(obj)
:获取对象的所有 value 形成的数组entries(obj)
:获取对象的所有 key 和 value 形成的二维数组。格式:[[k1,v1], [k2,v2],...]
assign(dest, ...src)
:将多个 src 对象的值 拷贝到 dest 中。 (第一层为深拷贝,第二层为浅 拷贝)
const person = {
name: "jack",
age: 21,
language: [ 'java ', 'js ', 'css ']
}
console.log(Object.keys(person));//["name", "age", "language"]
console.log(Object.values(person));//["jack", 21, Array(3)]
console.log(Object.entries(person));//[Array(2), Array(2), Array(2)]
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
//Object.assign 方法的第一个参数是目标对象,后面的参数都是源对象。
Object.assign(target, source1, source2);
console.log(target)//{a: 1, b: 2, c: 3}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
声明对象简写
const age = 23
const name = "张三"
// 传统
const person1 = { age: age, name: name }
console.log(person1)
// ES6:属性名和属性值变量名一样,可以省略
const person2 = { age, name }
console.log(person2) //{age: 23, name: "张三"}
2
3
4
5
6
7
8
9
10
对象的函数属性简写
let person = {
name: "jack",
// 以前:
eat: function (food) {
console.log(this.name + "在吃" + food);
},
// 箭头函数版:这里拿不到this
eat2: food => console.log(person.name + "在吃" + food),
// 简写版:
eat3(food) {
console.log(this.name + "在吃" + food);
}
}
person.eat("apple");
2
3
4
5
6
7
8
9
10
11
12
13
14
对象拓展运算符
拓展运算符 ( ... ) 用于取出参数对象所有可遍历属性然后拷贝到当前对象。
// 1、拷贝对象 (深拷贝)
let person1 = { name: "Amy", age: 15 }
let someone = { ...person1 }
console.log(someone) //{name: "Amy", age: 15}
// 2、合并对象
let age = { age: 15 }
let name = { name: "Amy" }
let person2 = { ...age, ...name } //如果两个对象的字段名重复,后面对象字段值会覆盖前面对象的字段值
console.log(person2) //{age: 15, name: "Amy"}
2
3
4
5
6
7
8
9
10
8.map
map()
:接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。
let arr = [ '1 ', '20', '-5 ', '3 '];
console.log(arr)
arr = arr.map(s => parseInt(s));
console.log(arr)
2
3
4
5
9.reduce
语法:arr.reduce(callback,[initialValue])
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值 (或者上一次回调函数的返回值) ,当前元素值,当前索引,调 用 reduce 的数组。
callback (执行数组中每个值的函数,包含四个参数)
1 、previousValue (上一次调用回调返回的值,或者是提供的初始值 (initialValue) )
2 、currentValue (数组中当前被处理的元素)
3 、index (当前元素在数组中的索引)
4 、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
const arr = [1,20,-5,3];
//没有初始值:
console.log(arr.reduce((a,b)=>a+b));//19
console.log(arr.reduce((a,b)=>a*b));//-300
//指定初始值:
console.log(arr.reduce((a,b)=>a+b,1));//20
console.log(arr.reduce((a,b)=>a*b,0));//-0
2
3
4
5
6
7
10.this 使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<script>
// 什么时候使用箭头
// setTimeout(function () {
// console.log(this);
// }, 1000)
//
// setTimeout(() => {
// console.log(this);
// }, 1000)
// 问题: 箭头函数中的this是如何查找的了?
// 答案: 向外层作用域中, 一层层查找this, 直到有this的定义.
// const obj = {
// aaa() {
// setTimeout(function () {
// console.log(this); // window
// })
//
// setTimeout(() => {
// console.log(this); // obj对象
// })
// }
// }
//
// obj.aaa()
const obj = {
aaa() {
setTimeout(function () {
setTimeout(function () {
console.log(this) // window
})
setTimeout(() => {
console.log(this) // window
})
})
setTimeout(() => {
setTimeout(function () {
console.log(this) // window
})
setTimeout(() => {
console.log(this) // obj
})
})
},
}
obj.aaa()
</script>
</body>
</html>
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61