ES6 是 ECMAScript 的第 6 个版本。它与 2015 年 6 月正式发布,正式名称为 ECMAScript 2015,通常 ES6 泛指 ECMAScript 2015 及其后续的版本
ECMAScript 是一种由 ECMA 国际(前身为欧洲计算机制造商协会,英文:European Computer ManufacturersAssociation)通过 ECMA-262 标准化的脚本程序设计语言,它定义了该脚本语言的各种元素、结构、语法、运算符等等。而 JavaScript 则是该标准的具体实现
let 关键字 let
允许你声明一个作用域被限制在块 ( {}
)中的变量。与 var
关键字不同的是,let
声明的变量不会在作用域中被提升
let 声明与 var 声明的区别:
特点 var
声明let
声明变量提升 Yes No 作用域 函数级作用域 块级作用域 重复声明 Yes No 全局对象 Yes No
变量提升:
1 2 3 console .log (age); let age = 38 ;
作用域:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { let a = 666 ; { let b = 'hello' } console .log (a); console .log (b); } function f1 ( ) { let n = 5 ; if (true ) { let n = 10 ; } console .log (n); } f1 ()
重复声明:
1 2 3 4 let num = 10 ;let num = 20 ;console .log (num)
全局对象:
1 2 3 let a = 666 ;console .log (window .a , a)
const 关键字 const
关键字用于声明一个常量,其特点和 let
声明一样(存在块作用域),但常量的值是无法(通过重新赋值)改变的
例:
1 2 3 4 5 6 7 8 9 10 11 const fav = 7 ;fav = 20 ; const fav = 20 ;var fav = 20 ;let fav = 20 ;const obj = {name : 'Tom' };obj.name = 'Bob' ; obj = {};
模版字符串(Template strings ) 模板字符串 是允许嵌入表达式的字符串字面量。你可以使用多行字符串和字符串插值功能
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 let mutLineStr = `string line1 string line2` ;console .log (mutLineStr);let author = "李白" ;let mustache = ` 静夜思 ${author} xxx ` ;console .log (mustache)
对象字面量增强 相对于 ES5,ES6 的对象字面量得到了很大程度的增强。这些改进使 JavaScript 代码更加简洁同时更易于理解
对象属性简写 例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var type = 'rock' ;var heat = '50%' ;var music = { type : type, heat : heat }; console .log (music); var type = 'rock' ;var heat = '50%' ;var music = { type, heat }; console .log (music);
对象方法简写 例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var type = 'rock' ;var heat = '50%' ;var music = { type : type, heat : heat, description : function ( ) { return '当前音乐风格为' + this .type + ',' + this .heat + '都喜欢' ; } } console .log (music.description ()); var type = 'rock' ;var heat = '50%' ;var music = { type, heat, description ( ) { return `当前音乐风格为${this .type} ,${this .heat} 都喜欢` ; } } console .log (music.description ());
PS:使用 ES6 简写的方法不能作为构造函数来调用( new
),否则将会报错
展开语法(Spread syntax ) 展开语法 可以在创建字面量 对象/数组时,将对象/数组在语法层面展开
1.对象展开:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 let chinese = { skin : "yellow" , hair : "black" , sayHi ( ) { console .log ("Are you ok?" ); }, }; let CXK = { slill : "jump sing rap and play basketball" , song : "啊哈哈哈" , }; let linge = { ...chinese, ...CXK , }; console .log (linge);
2.数组展开:
1 2 3 4 5 6 7 8 9 10 let arr1 = [10 , 20 , 30 ];let arr2 = [40 , 50 , 60 ];let arr3 = [...arr1, ...arr2, 70 ];console .log (arr3); let arr1 = [10 , 23 , 54 , 446 , 56 , 2 ];let max = Math .max (...arr1);console .log (max);
解构赋值(Destructuring ) 解构赋值 可以将属性/值从对象/数组中取出,并赋值给其它变量
1.数组的解构赋值:
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 let [a, b, c] = [1 , 2 , 3 ];console .log (a, b, c); let [ , y, z] = [4 , 5 ];console .log (y); console .log (z) let [a, [b], d] = [1 , [2 , 3 ], 4 ]; console .log (a, b, d) let x = 1 ;let y = 2 ;[x, y] = [y, x]; let [a=5 , b=7 ] = [1 ]; console .log (a); console .log (b); let [v, m, n] = "大前端" ;console .log (v, m, n);
2.对象的解构赋值:
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 let {x, y, z = 100 } = {x : 10 , y : 20 }console .log (x); console .log (y); console .log (z) var {a : num1 = 10 , b : num2 = 5 } = {a : 3 }; console .log (num1); console .log (num2); let obj = { p : [ 'Hello' , { y : 'World' } ] }; let { p, p : [x, { y }] } = obj;console .log (x); console .log (y); console .log (p) let {toString : s} = 123 ; s === Number .prototype .toString let {toString : s} = true ; s === Boolean .prototype .toString
4.函数参数的解构赋值:
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function test2 ({ name, age, gender, height = 180 } ) { console .log (name, age, gender, height); } test2 ({ name : "波波" , age : 38 , gender : "男" }); test2 ({ name : "波波" , age : 38 , gender : "男" , height : 160 });
PS:解构赋值语法实际上是一种 模式匹配 + 变量赋值 的混合,只要等号两边的模式相同,左边的变量就会被赋予对应的值
如:p: [x, { y }]
模式中 p 是模式匹配,但不是变量赋值,而 x 和 y 是模式匹配 + 变量赋值
箭头函数(Arrow function ) 箭头函数 是对函数表达式( 匿名函数 )的一种简写形式
语法:
1 2 3 4 5 6 7 8 9 10 11 12 let 函数名 = (形参1 , 形参2 ... 形参N ) => { 函数体 }
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 let fn1 = function (name ) { return name + "你好吗?" ; }; let fn1 = name => name + "你好吗?" ;let fn5 = function (name, age ) { console .log (name + "你好吗" ); return age + 10 ; }; let fn5 = (name, age ) => { console .log (name + "你好吗" ); return age + 10 ; };
参数默认值 函数形参可以指定一个初始值,当该形参没有传递实参时则该参数的值就是初始值( 默认值 )
例:
1 2 let fn = (a, b = 10 ) => console .log (a + b);fn (10 )
剩余参数(Rest Parameters ) 如果函数的最后一个形参以...
为前缀,则它将成为一个由剩余参数组成的数组
在箭头函数中不能通过 arguments
来获取实参
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 function fun1 (...theArgs ) { console .log (theArgs.length ); } fun1 (5 , 6 , 7 ); function multiply (multiplier, ...theArgs ) {return theArgs.map (function (element ) { return multiplier * element; }); } var arr = multiply (2 , 1 , 2 , 3 );console .log (arr);
this 指向 箭头函数中的 this
变量由上下文环境决定,而不是由 new
关键字来决定,因此箭头函数不能做为构造函数( new )来调用
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 let Fn = (name, age ) => { this .name = name this .age = age } var obj = new Fn ('超哥' , 20 ) var obj = { name : 'obj' , persons : { name : '波波' , sayHi : function ( ) { console .log ('我的名字是1:' , this .name ) setTimeout (() => { console .log ('我的名字是2:' , this .name ) setTimeout (() => { console .log ('我的名字是3:' , this .name ) }, 1000 ) }, 1000 ) } } } obj.sayHi ()
class 关键字 ES6 提供了 class 关键字,用来定义一个类
语法:
1 2 3 4 5 6 7 8 9 class 名称 [extends ] { } const 名称 = class [名称] [extends ] { }
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Rectangle2 { constructor (height, width ) { this .height = height; this .width = width; } }; console .log (Rectangle .name ); let Rectangle = class { constructor (height, width ) { this .height = height; this .width = width; } }; console .log (Rectangle .name );
类( class ) JavaScript 语言中,创建实例对象的传统方法是通过构造函数,如果要实现继承则需要借助原型
而 ES6 中的 class 依然是建立在原型上的,因此 ES6 中的 class 可以看作是一个语法糖,它使 JavaScript 在语法上更像面向对象
Js 中使用 class 声明的类,实质上是一种特殊的函数,它只能使用 new
关键字来调用,并且 class 声明不会有提升
例:
1 2 3 4 5 6 7 8 9 10 class Point {} console .log (typeof Point ); console .log (Point === Point .prototype .constructor )
PS:class 中的代码都执行在严格模式( strict mode )下。比如,构造函数,静态方法,原型方法,getter 和 setter 都在严格模式下执行
构造方法( constructor ) constructor 是类中的一个特殊的方法,该方法用于创建和初始化一个由class
创建的对象
一个类中只能有一个名为 “constructor” 的特殊方法。类中出现多个构造函数( constructor )方法将会抛出一个 SyntaxError 错误
如果没有指定构造函数( constructor )方法,则会使用一个默认的构造函数( constructor )来初始化实例
实例属性 / 原型方法 例:
1 2 3 4 5 6 7 8 9 class Foo { bar = 'hello' ; baz = 'world' ; print ( ) { console .log (`${this .bar} ${this .baz} ` ); } } (new Foo ).print ();
在 ES5 中要给实例对象添加属性需要在构造函数或方法内使用 this 来添加,如果要添加方法则会将方法添加构造函数的原型prototype上。而上面的写法相比 ES5 的写法更加简洁,一眼就能看出,Foo
类有两个实例属性和一个原型方法
getter & setter ( 存取值方法 ) 在“类”的内部可以使用get
和set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class MyClass { get prop () { return 'getter' ; } set prop (value ) { console .log ('setter: ' +value); } } let inst = new MyClass ();inst.prop = 123 ; console .log (inst.prop ) class Hero { v = 100 ; get getV () { return this .v ; } set setV (value ) { this .v = value; } } var obj = new Hero ();console .log (obj.getV ); obj.setV = 200 ; console .log (obj.getV );
静态属性 / 静态方法 如果在一个属性或方法前,加上static
关键字,则该属性或方法将不会被添加到实例上,它是直接通过类来访问或调用
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function Foo ( ) { } Foo .prop = 1 Foo .classMethod = function ( ) { console .log (Foo .prop ); } Foo .classMethod () class Foo { static prop = 1 ; static classMethod ( ) { console .log (this .prop ) } } Foo .classMethod () var foo = new Foo ();foo.classMethod ()
extends 关键字 extends 关键字 用于创建一个类作为另一个类的一个子类
例:
1 2 3 4 5 6 7 class Parent {} class Child extends Parent { constructor ( ) { super (); this .age = 18 ; } }
类的继承 class 可以通过extends
关键字实现继承,让子类继承父类的属性和方法
当子类继承某个父类时,子类必须先在constructor
方法中使用super()
来调用父类构造函数,否则就会报错
这是因为extends
关键字在继承时,子类的实例需要通过父类得到。在调用super()
方法时,会先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,因此如果不调用super()
方法,子类就得不到自己的this
对象
例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Point { static s = 'static' constructor (x, y ) { this .x = x; this .y = y; } } class ColorPoint extends Point { constructor (x, y, color ) { this .color = color; super (x, y); this .color = color; } } console .log (ColorPoint .s , ColorPoint .__proto__ === Point )