es6基础知识点1
在项目中已经不知不觉开始使用es6语法,比如箭头函数、let关键字等等。现在来梳理一下ES6知识点。
关于ES6
ECMAScript 6(ES6)是JavaScript的最新标准化版本。es6标准化已经很长一段时间了,浏览器也广泛支持。但并非所有浏览器都已经支持es6,此时则需要使用转换器将代码转换成es5版本,如Babel。
例如:
一段es6代码:
let nums = [1,2,3];
let doubleNums = nums.map((e) => e*2);
Babel会将其转换为一下es5代码:
"use strict";
var nums = [1,2,3];
var doubleNums = nums.map(function (e){
return e * 2
});
下面开始梳理一些es6的知识点。
1. let
1.1 let基本用法
let的用法类似var,但是声明的变量,只在let所在的代码块内有效。
例如:
let x = 1;
if (x == 1) {
let x = 2;
console.log(x); // 2;
}
console.log(x); // 1
首先,声明了变量x,并赋值1
然后,x在if块中声明一个具有相同名称的新变量,赋值2
最后,输出if内x为2,外部不受影响为1(块内有效,相当于if快内的x是一个新变量)
注意:如果使用var,则外部也会变成2
1.2 let与全局变量
当使用var声明全局变量时,会将变量添加到全局对象中,在web浏览器情况下,全局对象为window。
例如:
var a = 1;
console.log(window.1);//1
但是使用let关键字声明变量,不会将变量添加到全局对象中。
例如:
var b = 2;
console.log(window.b);//undefined
1.3 let在for循环中
使用var时,有一个问题:
for(var i = 0;i < 5;i++) {
setTimeout(function(){
console.log(i);//结果为:5次5
},1000);
}
原因是经过5次迭代,i的变量为5,并且传递给了setTimeout的回调函数。
在es5中,需要通过创建另一个作用域来解决上述问题,以便每个回调函数实例引用一个新变量。而要创建一个新的范围,需要创建一个函数。通常,使用IIFE模式如下:
for(var i = 0;i < 5;i++) {
(function(j){
setTimeout(function(){
console.log(j);//0 1 2 3 4
},1000);
})(i);
}
在es6中,let关键字在每个循环迭代中声明一个新变量,因此只需要将var改成let即可:
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}
1.4 let 变量提升
首先,看一个例子:
(function(){
console.log(name);//ReferenceError: name is not defined (使用var输出undefined)
let name = 'Summer';
})();
在函数中,name在声明之前访问会导致ReferenceError: name is not defined。以此可知,JavaScript引擎会将let声明的变量提升到块的顶部,但是如果在声明之前引用,则会ReferenceError。如果使用var则会发生变量提升,name在声明之前已经存在了,只是没有值,所以输出undefined。
1.5 TDZ
使用let声明变量存在暂时死区(时滞盲区)TDZ。是指从块开始到处理变量声明的时间。
(function(){
// 进入新的块范围, TDZ start
let log = function () {
console.log(name); // ReferenceError: name is not defined
};
// 这是TDZ并访问name变量
// 如果在此调用log(),将得到 ReferenceError
let name = 1; // TDZ 结束
log(); // 在TDZ之外调用
})();
首先进入块范围,TDZ开始。
然后,日志函数表达式访问name变量。但是该log()函数未执行,因此是没问题的。
再然后,声明name变量,并赋值1。从块范围开始到name变量被访问的时间成为时间死亡区(TDZ)。JavaScript引擎处理声明,TDZ结束。
最后,调用log()访问name变量
在let变量声明之前,是一个不存在的变量,类型是未定义的。
(() => {
//TDZ 开始
console.log(typeof a) //undefined
var a = 1;
console.log(typeof b) //ReferenceError
let b = 2; //TDZ 结束
})();
注意:let在同一个块范围中,不能重复声明
2. const
在es6中,const关键字用于声明常量。声明的变量只读,不能修改,且声明变量时必须初始化一个值。(通常,JavaScript的常量变量名大写)
除了以上,const与let声明变量基本一样。
2.1 常量 and 对象
使用const创建的变量是只读的,但是不以为着const变量引用是不可变的实际值。(what???蒙圈!!!)
举例说明:
const person = {name:'Summer'};
person.name = 'Minya';//正确的,不会报错
console.log(person.name);//Minya
可以修改对象里属性的值,但是不能给整个对象重新赋值,比如:
person.name = {name:'who'};//TypeError
如何确保对象的属性值也是不可变的?可以使用Object.freeze冻结:
const person = Object.freeze({name:'Summer'});
person.name = 'Minya';
console.log(person.name);//Summer
Object.freeze是浅冻结,如:
const person2 = Object.freeze({
name:'Summer',
friends:{
first:'Minya',
second:'who'
}
});
//修改
person2.friends.first = 'handsome';//此时值已修改成功
2.2 for循环
使用for…of,使用let时:
var nums = [1,2,3];
for(let num of nums){
console.log(num) //1 2 3
}
使用const:
var nums = [1,2,3];
for(const num of nums){
console.log(num) //1 2 3
}
//以上代码是有效的,在每次迭代中for...of为const创建一个新的绑定。即const常量是每次迭代中创建的
错误用法:
for (const i = 0; i < nums.length; i++) { // TypeError: Assignment to constant variable.
console.log(nums[i]);
}
//错误原因,声明只在循环体开始之前被创建(一次),不能修改
3. 箭头函数
首先,es5函数表达式写法如下:
var add = function(x,y) {
return x+y;
}
add(1,2);//3
将上述函数表达式换成箭头函数表达式写法,如下:
var add = (x,y) => x+y;
add(1,2);//3
console.log(typeof add) //function
console.log(add instanceof Function) //true 箭头函数也是Function的一个实例
3.1 参数
对于参数在两个或两个以上的箭头函数,可以使用以下写法:
(x1,x2,...,xn) => expression;
//其中 =>expression 等价于 =>{return expression;}
举例说明:
var nums = [2,3,1];
nums.sort((a,b) => b-a);//排序
console.log(nums);//[3,2,1]
单个参数:
x => {语句}
或者:
(x) => {语句}
如:
var names = ['John', 'Mac', 'Peter'];
var lengths = names.map(name => name.length);
console.log(lengths);
没有参数:
() => {语句}
如:
var names = ['John', 'Mac', 'Peter'];
var lengths = () => names.length
lengths();//3
参数与括号之间不能换行:
//以下写法错误,SyntaxError
var add = (x,y)
=> x+y;
//正确写法
var add = (x,y) =>
x+y;
//正确写法
var add = (
x,
y) =>
x+y;
3.2 箭头函数与es5的function函数比较
区别:
1.在箭头函数中,本身不存在this对象;
2.不可以使用new命令(不可以当做构造函数);
3.不可以使用arguments对象,不存在。可以使用rest参数代替;
4.不能使用super
关于this的区别,举例说明:
在es5的函数中:
var add = function(x){
this.x = x
setTimeout(function(){
console.log(this.x)//undefined,此时this是指向setTImeout的回调函数function里的
},0);
}
add(1);
在箭头函数中:
var add = function(x){
this.x = x
setTimeout(() => {
console.log(this.x) //1 箭头函数没有this,所以这里的this指向add这个function的this
},0);
}
add(1);
4. 参数
4.1 默认参数
举例说明:
function add(x=10){
console.log(x)
}
add();//10
add(undefined);//10
add(20);//20
4.2 rest参数(…)
不定数量的参数:
function add(x1,x2,...xn){
//...
}
//最后一个参数xn前面加上三个点(...)称为rest参数(...xn)
比如add(1,2,3,100,200,300),此时,x1=1,x2=2,xn=[3,100,200,300]
本篇主要总结let、const、箭头函数、参数,下篇继续总结es6知识点。