ES6学习总结
JavaScript
是一个持续演进的编程语言,并由浏览器厂商、开发者和社区成员组成的委员会制定标准。委员会引入了JavaScript
历史上的最大更新 ES6
(ES2016),而 ES7
是年度更新的第一版(ES2017)。
2、ES6
和ES7
优点
-
-
简化常见编程模式
-
使代码更容易编写以及定制底层的
JavaScript
行为。
-
3、新特性
-
-
类
Class
可以让开发者更容易地编写面向对象程序,并安全地扩展extend
JavaScript内建对象。 -
箭头函数
Arrow functions
、默认参数default parameters
和数组的遍历方法array convenience methods
使得常用功能更容易编写,而不需要在项目之间复制黏贴代码。 -
JavaScript
的异步处理流和嵌套回调让人难以理解,所以 ES6 中引入了promises
、迭代器和生成器iterators, and generators
以简化异步代码,让控制流更直观而不易出错。
-
4、ES6
基础---let
命令
-
- 用于声明(局部)变量,类似于var(全局),但是声明的变量只在let命令所在的代码块有效。
-
-
创建块级作用域(下面详细介绍)
1 if(true){ 2 let a=10; 3 var b=1; 4 } 5 console.log(a); //Uncaught ReferenceError: a is not defined 6 console.log(b); //1
-
没有变量提升
1 console.log(typeof str); //undefined 2 var str = 10; 3 4 console.log(typeof abc); //Uncaught ReferenceError: abc is not defined 5 let abc = 10;
-
不允许重复声明
1 let a=10; 2 let a=20; 3 console.log(a); //Uncaught SyntaxError: Identifier 'b' has already been declared 4 5 var a=10; 6 var a=20; 7 console.log(a); //20
-
暂时性死区
在块级作用域中使用
let
声明变量时,块级作用域会形成一个封闭的环境,不能访问外部声明的变量1 var c = 19; 2 if(true) { 3 console.log(c); 4 let c; //Uncaught ReferenceError: c is not defined 5 }
-
5、为什么需要块级作用域?
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
-
- 第一种场景----内层变量可能会覆盖外层变量。
1 var tmp = 'hi'; 2 function f() { 3 console.log(tmp); //这里想使用外层的tmp='hi' 4 if (false) { //if代码块之内使用内层的tmp='hello' 5 var tmp = 'hello'; 6 } 7 } 8 f(); //但是输出结果是undefined,因为这里存在变量提升,导致内部tmp覆盖了外层的tmp
- 第一种场景----内层变量可能会覆盖外层变量。
-
- 第二种场景----用来计数的循环变量泄露为全局变量。
1 var s = 'hello'; 2 for (let i = 0; i < s.length; i++) { 3 console.log(s[i]); 4 } 5 console.log(i); // 5 6 //上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量
- 第二种场景----用来计数的循环变量泄露为全局变量。
6、ES6
基础---const
命令
const
声明一个只读的常量。
-
-
一旦声明,常量的值就不能改变
1 const PI = 3.1415; // 3.1415 2 PI = 3; // TypeError: Assignment to constant variable.
-
只声明,不赋值,也会报错
1 const a; // SyntaxError: Missing initializer in const declaration
-
-
-
与
1 if (true) { 2 const a = 5; 3 } 4 console.log(a); // Uncaught ReferenceError: a is not defined
-
-
-
1 var message = "Hello!"; 2 let age = 25; 3 4 // 以下两行都会报错 5 const message = "Goodbye!"; 6 const age = 30;
- 也没有变量提升,存在暂时性死区
1 if (true) { 2 console.log(a); //Uncaught ReferenceError: a is not defined 3 const a = 5; 4 }
-
7、ES6
声明变量的六种方法
-
ES5
只有两种声明变量的方法:var
命令和function
命令。ES6
除了添加let
和const
命令,另外两种声明变量的方法:import
命令和class
命令。所以,ES6
一共有6种声明变量的方法。
8、箭头函数
-
- ES6 允许使用“箭头”(
=>
)定义函数。1 var f = v => v;
- ES6 允许使用“箭头”(
-
- 上面箭头函数等同于
1 var f = function(v) { return v;};
- 上面箭头函数等同于
-
- 引入箭头函数的两个作用
- 更简短的函数书写,简化回调函数
1 // 正常函数写法 2 [1,2,3].map(function (x) { 3 return x * x; 4 }); 5 // 箭头函数写法 6 [1,2,3].map(x => x * x);
- 更简短的函数书写,简化回调函数
- 引入箭头函数的两个作用
-
- 使用时需注意
- 函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象。 - 不可以当作构造函数,也就是说,不可以使用
new
命令,否则会抛出一个错误。 - 不可以使用
arguments
对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。 - 不可以使用
yield
命令,因此箭头函数不能用作 Generator 函数1 //this对象的指向是可变的,但是在箭头函数中,它是固定的。 2 function foo() { 3 setTimeout(() => { 4 console.log('id:', this.id); 5 }, 100); 6 } 7 var id = 21; 8 foo.call({ id: 42 }); // id: 42 9 //箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域
- 函数体内的
- 使用时需注意
-
- 小测试:请问下面的代码中有几个this?
1 function foo() { 2 return () => { 3 return () => { 4 return () => { 5 console.log('id:', this.id); 6 }; 7 }; 8 }; 9 } 10 11 var f = foo.call({id: 1}); 12 13 var t1 = f.call({id: 2})()(); // id: 1 14 var t2 = f().call({id: 3})(); // id: 1 15 var t3 = f()().call({id: 4}); // id: 1
- 小测试:请问下面的代码中有几个this?
上面代码之中,只有一个this
,就是函数foo
的this
,所以t1
、t2
、t3
都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的this
,它们的this
其实都是最外层foo
函数的this
。
除了this
,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments
、super
、new.target
。
9、promise对象
-
- 异步编程的一种解决方案
- 避免了层层嵌套的回调函数,使用链式调用方式来组织代码,更加直观
- 提供统一的接口,使得控制异步操作更加容易。
- 三种状态
- Pending进行中
- Resolved已完成(又称Fulfilled)
- Rejected已失败
- 基本用法
1 //创造一个promise实例 2 var promise = new Promise(function(resolve, reject) { 3 // ... some code 4 5 if (/* 异步操作成功 */){ 6 resolve(value); 7 } else { 8 reject(error); 9 } 10 }); 11 //实例生成后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。 12 promise.then(function(value) { 13 // success 14 }, function(error) { 15 // failure 16 });
- promise.all()
- 异步编程的一种解决方案
-
-
-
var p = Promise.all([p1, p2, p3]);
-
p
的状态由p1
、p2
、p3
决定,分成两种情况。(1)只有
p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。(2)只要
p1
、p2
、p3
之中有一个被1 // 生成一个Promise对象的数组 2 var promises = [2, 3, 5, 7, 11, 13].map(function (id) { 3 return getJSON('/post/' + id + ".json"); 4 }); 5 6 Promise.all(promises).then(function (posts) { 7 // ... 8 }).catch(function(reason){ 9 // ... 10 }); //上面代码中,promises是包含6个 Promise 实例的数组,只有这6个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数
-
-
先到这里吧!有什么不对的地方望大家多多指点!