文章目录
ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。
ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。
ES6 let 与 const
ES2015(ES6) 新增加了两个重要的 JavaScript 关键字: let 和 const。
let 声明的变量只在 let 命令所在的代码块内有效。
const 声明一个只读的常量,一旦声明,常量的值就不能改变。
let 命令
代码块内有效
let 是在代码块内有效,var 是在全局范围内有效:
{
let a = 0; //let 块外即大括号外不能访问
var b = 1; //var 是在全局范围内有效
console.log(a); //输出0
console.log(b); //输出1
}
console.log(a); //报错 ReferenceError: a is not defined
console.log(b); //输出1
不能重复声明
let 只能声明一次 var 可以声明多次:
var a = 1;
var a = 2;
console.log(a); //输出2
let b = 3; //Identifier 'b' has already been declared
let b = 4; //let 不能重复申明一个变量名
console.log(b);
不存在变量提升
let 不存在变量提升,var 会变量提升:
console.log(a); // undefined
var a = "banana";
console.log(b); // Cannot access 'b' before initialization
let b = "apple";
const 命令
const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。
const pi = "3.1415";
console.log(pi); // 输出3.1415
pi = "1415926"; // 不能重新赋值,报错:TypeError: Assignment to constant variable
const pi = "1415926"; // 不能重复声明,报错:SyntaxError: Identifier 'pi' has already been declared
const pe; // 必须初始化,报错:SyntaxError: Missing initializer in const declaration
注意要点:
const 如何做到变量在声明初始化之后不允许改变的?其实 const 其实保证的不是变量的值不变,而是保证变量指向的内存地址所保存的数据不允许改动。此时,你可能已经想到,简单类型和复合类型保存值的方式是不同的。是的,对于简单类型(数值 number、字符串 string 、布尔值 boolean),值就保存在变量指向的那个内存地址,因此 const 声明的简单类型变量等同于常量。而复杂类型(对象 object,数组 array,函数 function),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了,所以使用 const 声明复杂类型对象时要慎重。
ES6 解构赋值
- 解构赋值是对赋值运算符的扩展。
- 他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
- 在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
解构模型
在解构中,有下面两部分参与:
- 解构的源,解构赋值表达式的右边部分。
- 解构的目标,解构赋值表达式的左边部分。
数组模型的解构(Array)
let [a,b,c] = [1,2,3];
console.log(a,b,c); //输出123
//可嵌套
let [d, [[e], f]] = [1, [[2], 3]];//d=1 ,e=2 ,f=3
//可忽略
let [g,,h] = [1,2,3];//g=1 ,h=3
//不完全解构
let [a = 1, b] = []; // a = 1, b = undefined
//剩余运算符
let [a, ...b] = [1, 2, 3];
//a = 1
//b = [2, 3]
//字符串等
//在数组的解构中,解构的目标若为可遍历对象,皆可进行解构赋值。可遍历对象即实现 Iterator 接口的数据。
let [a, b, c, d, e] = 'hello';
// a = 'h'
// b = 'e'
// c = 'l'
// d = 'l'
// e = 'o'
//解构默认值
let [a = 2] = [undefined]; // a = 2
当解构模式有匹配结果,且匹配结果是 undefined 时,会触发默认值作为返回结果。
let [a=3,b=a]=[];console.log(a,b);//33
let [a=3,b=a]=[1];console.log(a,b);//11
let [a=3,b=a]=[1,2];console.log(a,b);//12
对象模型的解构(Object)
let {foo,bar}={foo:'aaa',bar:'bbb'};
console.log(foo);//aaa
console.log(bar);//bbb
//可嵌套可忽略
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, { y }] } = obj;
// x = 'hello'
// y = 'world'
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, { }] } = obj;
// x = 'hello'
//不完全解构
let obj = {p: [{y: 'world'}] };
let {p: [{ y }, x ] } = obj;
// x = undefined
// y = 'world'
//剩余运算符
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
// a = 10
// b = 20
// rest = {c: 30, d: 40}
//解构默认值
let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;
ES6 字符串
字符串相关扩展
includes():返回布尔值,判断是否找到参数字符串。
startsWith():返回布尔值,判断参数字符串是否在原字符串的头部。
endsWith():返回布尔值,判断参数字符串是否在原字符串的尾部。
let str = 'hello world';
console.log(str.includes('world',7));//false
console.log(str.includes('world',6));//true
let url = 'admin/index.html';
console.log(url.startsWith("admin"));//true
console.log(url.startsWith("index"));//false
let url2 = 'admin/index.html';
console.log(url.endsWith("html"));//true
console.log(url.endsWith("index"));//false
字符串重复
console.log("Hello,".repeat(3));//Hello,Hello,Hello,
console.log("Hello,".repeat(3.3));//Hello,Hello,Hello,
模板字符串
模板字符串相当于加强版的字符串,用反引号 `,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。
let string = `hello\nworld`;
console.log(string);
//hello
//world
let str = `hello world`;
let tag = `
<div>
<p>p标签</p>
<p>字符串:${str}</p>
</div>
`;
console.log(tag);
/*
<div>
<p>p标签</p>
<p>字符串:hello world</p>
</div>
*/
注意要点:模板字符串中的换行和空格都是会被保留的
标签模板
标签模板,是一个函数的调用,其中调用的参数是模板字符串。
alert`Hello world!`;
// 等价于
alert('Hello world!');
箭头函数
箭头函数提供了一种更加简洁的函数书写方式。基本语法是:
参数 => 函数体
var f = v => v;
//等价于
var f = function(a){
return a;
}
f(1); //1
var f = (a,b) => {
let result = a+b;
return result;
}
f(6,2); // 8
Class 类
类定义
类表达式可以为匿名或命名。
// 匿名类
let Example = class {
constructor(a) {
this.a = a;
}
}
// 命名类
let Example = class Example {
constructor(a) {
this.a = a;
}
}
//类声明
class Example {
constructor(a) {
this.a = a;
}
}
class Animal {
constructor(name,age,color){
this.name = "猫";//默认它是一只猫
this.age = 2;
this.color = "黑色";
}
run(){
console.log("会跑");
}
predation(){
console.log("会捕食");
}
reproduction(){
console.log("繁衍");
}
}
class Cat extends Animal {
constructor(name,age,color,varieties){
super(name,age,color);
this.varieties = "布偶猫";
}
climbtree(){
console.log("爬树");
}
CatchMouse(){
console.log("抓老鼠");
}
}
let Cat1 = new Cat();
let cat = `一只${Cat1.color}的${Cat1.name},品种:${Cat1.varieties}它${Cat1.age}岁了,它会`;
console.log(cat);
Cat1.run();
Cat1.predation();
Cat1.reproduction();
Cat1.CatchMouse()
Cat1.climbtree()
/*
一只黑色的猫,品种:布偶猫它2岁了,它会
会跑
会捕食
繁衍
抓老鼠
爬树
*/
class Dog extends Animal {
constructor(name,age,color,varieties){
super(name,age,color);
this.name = "狗";
this.varieties = "哈士奇";
}
swimming(){
console.log("游泳");
}
watchHouse(){
console.log("看家");
}
}
let Dog1 = new Dog();
let dog = `一只${Dog1.color}的${Dog1.name},品种:${Dog1.varieties}它${Dog1.age}岁了,它会`;
console.log(dog);
Dog1.run();
Dog1.predation();
Dog1.reproduction();
Dog1.swimming();
Dog1.watchHouse();
/*
一只黑色的狗,品种:哈士奇它2岁了,它会
会跑
会捕食
繁衍
游泳
看家
*/
Map 与 Set
Map 对象
Map结构提供了“值—值”的对应,是一种更完善的Hash结构实现。如果你需要“键值对”的数据结构,Map比Object更合适。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
var m = new Map();
var o = {p: "Hello World"};
m.set(o, "content")
m.get(o) // "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false
注意:只有对同一个对象的引用,Map结构才将其视为同一个键。这一点要非常小心。
var map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined
上面代码的set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined。
如果Map的键是一个简单类型的值(数字、字符串、布尔值),则只要两个值严格相等,Map将其视为一个键,包括0和-0。另外,虽然NaN不严格相等于自身,但Map将其视为同一个键。