1. ES6的新的变量声明:let和const
1.1 关于预解析
用var 定义的变量,存在预解析的情况,所以下列输出undefined
console.log(a); //undefined
var a = 123;
但是用let定义的变量不存在预解析,所以报错输出b is not defined
console.log(b); //b is not defined
let b = 456;
1.2 是否允许变量重复
用var定义变量可以允许变量重复,后来的赋值会覆盖先前赋值,例如
var flag = 123;
var flag = 456;
console.log(flag) //输出456
在同一作用域内,用let定义的变量不允许变量重复。
let flag = 123;
let flag = 456;
console.log(flag); //SyntaxError: Identifier has already been declared
1.3 块级作用域
ES6中引入了块级作用域的概念:
if(1) {
var a = 123;
let b = 456;
}
console.log(a); //123
console.log(b); //b is not defined
{
let c = 111;
console.log(c); //111
}
console.log(c); //c is not defined
用let在块内部定义的变量,外部是不能够访问的
for (let i = 0; i < 3; i++) {
console.log(i)
}
console.log(i) //i is not defined
for循环中用let定义i的值,相当于形成了一个块级作用域,i仅在作用域内部有作用,外部是不能访问到的。并且在块级作用域内部,变量也只能先声明再使用。
1.3 const的特性
上面的特性对let和const均适用,以下是const独有的特性:
1.const用来声明常量,const声明的常量不允许重新赋值。
2.const声明的常量必须初始化。
const n = 1;
n = 2; //TypeError: Assignment to constant variable.
const abc; //SyntaxError: Missing initializer in const declaration
2.变量的解构赋值
2.1 数组的解构赋值
一次定义多个变量的时候,我们可以用如下方式
var a = 1;
var b = 2;
var c = 3;
//或者写到一起
var a = 1,b = 2,c = 3;
使用解构赋值:
let [a,b,c] = [1,2,3];
或者使用如下的方法,给变量a一个默认值111,如果a未被赋值,就赋值给a默认值111
let [a=111,b,c] = [1,2,3]
let [d=111,e,f] = [,5,6]
console.log(a,b,c) //1,2,3
console.log(d,e,f) //111,5,6
2.2 对象的解构赋值
let {foo, bar} = {foo: 'hello', bar: 'hi'}
console.log(foo,bar) //hello hi
在解构赋值的时候可以给对象赋个别名,如:
let {foo:abc, bar} = {foo: 'hello', bar: 'hi'}
console.log(abc,bar) //hello hi
console.log(foo) //foo is not defined
注意:如果给对象起了别名,那么原来的名字就无效了。
对象的结构赋值也可以对内置对象来使用:
let {cos, sin, random} = Math;
console.log(typeof cos) //function
console.log(typeof sin) //function
console.log(typeof random) //function
2.3 字符串的解构赋值
let [a,b,c,d,e] = "hello"
console.log(a,b,c,d,e) //h e l l o
let [a,b,c,d] = "hello"
console.log(a,b,c,d) //h e l l
如果想获取字符串的长度,用数组的解构赋值无法获取,可以用对象的解构赋值来进行。
let [a,b,c,d,e,length] = "hello"
console.log(a,b,c,d,e) //h e l l o
console.log(length) //undefined
let {length} = "hello";
console.log(length) // 5
2.4 字符串相关扩展
几个方法:
includes() 判断字符串是否包含指定的子串,(有的话返回true,否则返回false)。
参数一:匹配的子串,参数二:从第几个开始匹配。
startswith() 判断字符串是否以特定的子串开始。
endswith() 判断字符串是否以特定的子串结束。
console.log("hello world".includes("he")) //true
console.log("hello world".includes("he", 5)) //false
let url = "/index.html"
console.log(url.endsWith("html")) //true
console.log(url.startsWith("/index")) //true
模板字符串:用反引号``表示模板,模板中的内容可以有格式缩进,通过${}
的方式填充数据(可以在其中调用函数)
2.5 函数相关扩展
2.5.1 参数默认值
通常我们在函数定义变量的时候会在未给变量传参的时候给它附一个默认值,如下:
function foo (param){
let p = param || "hello";
console.log(p)
}
foo("hi") //hi
foo() //hello
ES6的写法如下:
function foo(param = "hello"){
console.log(param)
}
foo("hi") //hi
foo() //hello
2.5.2. 参数解构赋值
function foo({uname="lisi",age=13}={}){
console.log(uname,age)
}
foo() //lisi 13
foo({uname: 'zhangsan', age:15}) //zhangsan 15
2.5.3. rest参数
function foo(a,b,...rest){
console.log(a,b,rest);
}
foo(1,2) //1 2 []
foo(1,2,3) //1 2 [ 3 ]
foo(1,2,3,4,5) //1 2 [ 3, 4, 5 ]
2.5.4. 扩展运算符…
作用:把数组拆开
function foo(a,b,c,d){
console.log(a+b+c+d)
}
let arr = [1,2,3,4];
foo(...arr) //10
扩展运算符应用:合并数组
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = [...arr1, ...arr2]
console.log(arr3) //[ 1, 2, 3, 4, 5, 6 ]
2.5.5 箭头函数
function v(){
return v;
}
//等效于
let foo = v => v;
箭头函数的注意事项:
- 箭头函数中的this取决于函数定义时的this,而不是调用。
function foo(){
//使用call调用foo时,这里的this就是call的第一个参数
console.log(this);
setTimeout(() => {
console.log(this.num)
}, 100);
}
foo.call({num:1}) //{ num: 1 }
//1
扩展几个例子:常见的setTimeOut+箭头函数的应用
例1:
var name = "windowsName";
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
},100);
}
};
a.func2() // this.func1 is not a function
在这个例子中setTimeout
中的function的this指向是在调用的时候确定的,最后调用 setTimeout
的对象是 window,但是在 window 中并没有 func1 函数。
例2:
var name = "windowsName";
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( () => {
this.func1()
},100);
}
};
a.func2() // Cherry
ES6 的箭头函数是可以避免 ES5 中使用 this 的坑的。箭头函数的 this 始终指向函数定义时的 this,而非执行时。箭头函数需要记着这句话:“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this 为 undefined”。
- 箭头函数不可以new。
- 箭头函数不可以使用
arguments
获取参数列表,可以使用rest
参数代替。
let foo = (...param)=>{
console.log(param)
}
foo(123,345) //[ 123, 345 ]