ES6
ES6是什么
ECMAScript 6.0(简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
为什么使用ES6
每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方:
- 变量提升特性增加了程序运行时的不可预测性
- 语法过于松散,实现相同的功能,不同的人可能会写出不同的代码
ES6新增语法
let
ES6中新增了用于声明变量的关键字let:
let声明的变量只在所处于的块级有效(一个大括号内)
if (true) {
let a = 10;
}
console.log(a) // a is not defined
if (true) {
var a = 10;
}
console.log(a); //10
//防止循环变量变成全局变量
for(var i =0;i<2;i++) {
}
console.log(i); //2
for (let i = 0; i < 2; i++) {
}
console.log(i); //i is not defined
let不存在变量提升
console.log(a); // a is not defined
let a = 20;
let暂时性死区
利用let声明的变量会绑定在这个块级作用域,不会受外界的影响
<script>
var tmp = 123;
if (true) {
console.log(tmp); //Cannot access 'tmp' before initialization
let tmp = 20;
}
</script>
let 声明的tmp与整体进行绑定,在声明前无法调用tmp,也不受外界的tmp影响 。
注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
let经典面试题
var arr = [];
for (var i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0](); //2
arr[1](); //2
此题的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。
let arr = [];
for (let i = 0; i < 2; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[0](); //0
arr[1](); //1
此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值.
const
const:声明常量,常量就是值(内存地址)不能变化的量.
具有块级作用域
if (true) {
const a = 10;
}
console.log(a) // a is not defined
声明常量时必须赋值
const PI; // Missing initializer in const declaration
常量赋值后,值不能修改
const PI = 3.14;
PI = 100; // Assignment to constant variable.
const ary = [100, 200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b']; //没用更改地址
ary = ['a', 'b']; // Assignment to constant variable. //更改了内存地址
小结
- const声明的变量是一个常量
- 既然是常量不能重新进行赋值,如果是基本数据类型,不能更改值,如果是复杂数据类型,不能更改地址值(可以更改里面的数据)
- 声明 const时候必须要给定值
let、const、var 的区别
- 使用 var 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
- 使用 let 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升
- 使用 const 声明的是常量,在后面出现的代码中不能再修改该常量的值
解构赋值
ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构.
数组解构
<script>
//数组解构允许我们按照一一对应的关系从数组中提取值
//然后将值赋值给变量
let arr = [1,2,3];
let [a,b,c,d,e] = arr;
console.log(a); //1
console.log(b); //2
console.log(c); //3
console.log(d); //undefined
console.log(e); //undefined
</script>
//如果解构不成功,变量的值为undefined
对象解构
<script>
let p = {
name:"zs",age:20};
let{
name,age} = p;
console.log(name); //zs
console.log(age); //20
let {
name:myname,age:myage} = p; // myName myAge 属于别名
console.log(myname); //zs
console.log(myage); //20
</script>
小结
- 解构赋值就是把数据结构分解,然后给变量进行赋值
- 如果结构不成功,变量跟数值个数不匹配的时候,变量的值为undefined
- 数组解构用中括号包裹,多个变量用逗号隔开,对象解构用花括号包裹,多个变量用逗号隔开
- 利用解构赋值能够让我们方便的去取对象中的属性跟方法
箭头函数
ES6中新增的定义函数的方式。
() => {
}
// ():代表是函数;
// =>:必须要的符号,指向哪一个代码块;
// {}:函数体
const fn = () => {
}
//代表把一个函数赋值给fn
函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
const sum = (n1,n2) => n1+n2;
console.log(sum(10,10));
如果形参只有一个,可以省略小括号
function fun1 (v) {
return v;
}
const fun2 = v =>v;
箭头函数不绑定this
箭头函数没有自己的this关键字
如果箭头函数中使用this,this关键字将指向箭头函数定义位置的this
function fun() {
console.log(this);
return () => {
console.log(this);
}
}
const obj = {
name:'zs'}
fun.call(obj); // {name : 'zs'}
const resfun = fun.call(obj);
resfun();
//{name : 'zs'}
//{name : 'zs'}
小结
- 箭头函数中不绑定this,箭头函数中的this指向是它所定义的位置,可以简单理解成,定义箭头函数中的作用域的this指向谁,它就指向谁
- 箭头函数的优点在于解决了this执行环境所造成的一些问题。比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局性),包括setTimeout和setInterval中使用this所造成的问题
面试题
var age = 100;
var obk = {
age: 20,
say: () => {
console.log(this.age)
}
}
obk.say(); //100
//箭头函数this指向的是被声明的作用域里面
//而对象没有作用域的
//所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域
剩余参数
剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式很方便的去声明不知道参数情况下的一个函数。
function sum (first, ...args) {
console.log(first); // 10
console.log(args); // [20, 30]
}
sum(10, 20, 30)
例子:
<script>
const sum = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
};
console.log(sum(10,20)) //30
console.log(sum(10,20,30)) //60
</script>
剩余参数和解构配合使用
let arr = [1,2,3,'zs','www']
let [s1,...s2] = arr;
console.log(s1); //1
console.log(s2); //[2,3,'zs','www']
ES6 的内置对象扩展
Array 的扩展方法
扩展运算符(展开语法)
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
let arr = [7,8,9];
console.log(...arr); //7 8 9
扩展运算符可以应用于合并数组
//合并数组
let arr1 = [1,2,3];
let arr2 = [4,5,6];
let arr3 = [...arr1,...arr2];
console.log(arr3); //[1,2,3,4,5,6]
//合并数组第二种方法
arr1.push(...arr2); //[1,2,3,4,5,6]
console.log(arr1);
将类数组或可遍历对象转换为真正的数组
//利用扩展运算符将伪数组转化为真正的数组
var odivs = document.getElementsByTagName('div');
var arry = [...odivs];
console.log(arry); // [div, div, div, div, div, div]
构造函数方法:Array.from()
将伪数组或可遍历对象转换为真正的数组
//定义一个集合
let arr5 = {
'0': '6',
'1': '7',
'2': '8',
length: 3
};
//转成数组
let arr6 = Array.from(arr5);
console.log(arr6) // ['6', '7', '8']
方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
let arr5 = {
'0': '6',
'1': '7',
'2': '8',
length: 3
};
//转成数组
let arr6 = Array.from(arr5,item => item*2);
console.log(arr6) // ['12', '14', '16']
注意:如果是对象,那么属性需要写对应的索引
实例方法:find()
用于找出第一个符合条件的数组成员,如果没有找到返回undefined
let arr = [{
id:1,
name:'zs'
},{
id:2,
name:'ds'
}];
let target = arr.find((item,index) => item.id == 2);
//找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
console.log(target);
实例方法:findIndex()
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let arr1 = [1,5,10,20];
let index = arr1.findIndex((value,index) => value > 9);
console.log(index); //2
实例方法:includes()
判断某个数组是否包含给定的值,返回布尔值。
[1,2,3].includes(2) //true
[1,2,3].includes(4) //false
String 的扩展方法
模板字符串
ES6新增的创建字符串的方式,使用反引号定义
let name = `zhangsan`;
console.log(name); //zhangsan
模板字符串中可以解析变量
let name1 = `jjj`;
let sayhello = `hello,my name is ${
name1}`;
console.log(sayhello); //hello,my name is jjj
模板字符串中可以换行
let rs = {
name:'asdsdsa',
age:22
}
let html = `
<div>
<span>${
rs.name}</span>
<span>${
rs.age}</span>
</div>
`;
console.log(html);
在模板字符串中可以调用函数
//模板字符串可以调用函数
const fn = () => {
return 1;
}
let o = `你好,我是${
fn()}`;
console.log(o); //你好,我是1
实例方法:startsWith() 和 endsWith()
- startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
- endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello world!';
var p = str.startsWith('Hello');
console.log(p); // true
var i = str.endsWith('!');
console.log(i); //true
实例方法:repeat()
repeat方法表示将原字符串重复n次,返回一个新字符串
var x = 'x'.repeat(6)
console.log(x); // "xxxxxx"
var l = 'hello'.repeat(2)
console.log(l); // "hellohello"
Set 数据结构
ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成 Set 数据结构
const s = new Set();
Set函数可以接受一个数组作为参数,用来初始化。
const s = new Set([1,2,3,4,5,5]);
console.log(s); //{1 2 3 4 5}
实例方法
- add(value):添加某个值,返回 Set 结构本身
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功
- has(value):返回一个布尔值,表示该值是否为 Set 的成员
- clear():清除所有成员,没有返回值
const s = new Set([1,2,3,4,5,5]);
console.log(s); //{1 2 3 4 5}
s.add(7).add(10);
console.log(s); //{1 2 3 4 5 7 10}
s.delete(3);
console.log(s); //{1 2 4 5 7 10}
var o = s.has(5);
console.log(o); //true
s.clear();
console.log(s); //{}
遍历
Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。
let p = new Set([1,2,3])
p.forEach(value => console.log(value));
//1
//2
//3
具体请看阮一峰ES6教程