let和const
let
javascript中没有块级作用域的概念,所以ES6新增了let关键字用来声明变量。let使javascript有了块级作用域,用let所声明的变量,只在该{}内有效。例如:
{ let a = 2; console.log(a); } console.log(a);
输出结果为:
let的另外两个特点:
避免了var声明函数时所导致的变量提升; 不允许在同一个作用域下,重复声明同一个变量。const
const拥有与let一样的特性,区别在于const声明的变量不能进行改变。例如:
{ const a = 78; a=3; console.log(a);//78 }
Class和Module
Class
ES6新增了类的用法,通过class关键字来定义类。例如:
class Person{ constructor(name,age){ this.name = name; this.age = age; } toString(){ return this.name+' is '+this.age+'.'; } }
代码定义了一个Person的类,其中包含一个constructor函数,这就是构造函数。而this关键字则代表实例对象。
类之间可以使用extends关键字来继承。例如:
class Man extends Person{ constructor(name,age,gen){ super(name,age); this.gen = gen; } toString(){ return super()+'his gen is'+this.gen; } }
类Man继承自Person类,在其构造函数constructor内部,super指的是父类Person;在函数toString内,super()表示父类的返回值,此时调动父类的toString方法。
Module
ES6可以通过export和import来实现模块的定义和加载。其中export是用户自定义对外返回的接口,而import则是引入模块并且创造命名空间,防止函数名冲突。例如:
//在circle.js中定义模块 export function area(radius){ return Math.PI * radius * radius; } export function circumference(radius){ return 2 * Math.PI * radius; }
//引入模块 import {area,circumference} from 'circle';
export可以输出变量、方法或者类。
不想为函数方法声明函数名时可以使用export default 来返回模块。需要注意的是,一个模块只能有一个 export default。
Promise对象
ES6提供了Promise构造函数,用来声明Promise实例。Promise是用来判断异步操作是否成功的一个对象。
基本用法:
var myPromise = new Promise(function(resolve,reject){ if(/*异步操作成功的判断语句*/){ resolve(value); } else{ reject(error); } }); myPromise.then(function(value){ //成功操作之后执行的代码块 },function(value){ //操作失败后的程序代码块 });
这部分很多新内容,可以参考链接:
https://www.cnblogs.com/tugenhua0707/p/4771528.html
Set和Map
Set
Set是一个构造函数,返回一个没有重复值的Set实例。例如:
var s = new Set([1,1,1,2,5,3,6,4,2,7]); console.log(s);
返回结果如下:
Set实例包括以下属性:
Set.prototype.constructor:构造函数,默认是Set构造函数;
Set.prototype.size:实例的成员长度。
Set包括以下方法:
add(value):添加成员;
delete(value):删除某个成员;
has(value):是否拥有某个成员;
clear():清除所有成员。
Map
javascript的对象只能是键值对,而其键只限字符串类型,为此ES6新增了Map构造函数,使得对象的键不再只是字符串。例如:
var m = new Map(); a = {p: "heiheihei"}; m.set(o,"hello"); console.log(m.get(o));//hello
Map包括以下属性:
size:返回成员总数。
Map包括以下方法:
set(key,value):设置一个成员;
get(key):获得一个成员;
has(key):是否拥有某个成员;
delete(key):删除某个成员;
clear():清除所有成员。
Map的方法通过键名获取值时,必须是与键名同一个内存空间的变量才可以。例如:
var m = new Map(); m.set(['aa'],111); m.get(['aa']);//undefined
即使set()和get()方法都使用[‘aa’],但是并不是同一个值,无法读取该键。
Map提供三个遍历器:
keys():返回键名的遍历器;
values():返回值的遍历器;
entries():返回所有成员的遍历器。
for…of遍历
for…of循环的作用
for…of循环可以遍历数组、类数组对象、Set和Map结构、Generator对象以及字符串,但不能遍历普通对象类型。
for…of循环和for…in循环的区别
for…of循环是有序遍历,而for…of循环则是无序遍历; for…in循环适用于键值对的普通对象遍历,而for…of循环则适用于除基本对象外的多种数据类型。Generator函数
Generator函数有两个特征:
function关键字后面有一个*; 函数体内部使用yield来调整内部状态。具体用法如下:
function* myfun(){ yield 'hi'; yield 'everyone'; yield 'byebye'; return 'end'; } var fun = myfun(); fun().next();//{value : 'hi',done : 'false} fun().next();//{value : 'everyone',done : 'false} fun().next();//{value : 'byebye',done : 'false} fun().next();//{value : 'end',done : 'false} fun().next();//{value : undefined,done : 'false}
结果如下:
第一次调用不返回值。之后每次通过next方法调用,执行一部分代码,直到遇到下一个yield而暂停。下一次执行next()方法时,从上一次暂停的地方继续开始执行后面的代码,直到下一个yield出现为止。
解构赋值
ES6可以按照一定的模式从数组和对象中提取值,对变量进行赋值,这被称为解构。例如:
数组的解构赋值
var [a,b,c] = [1,2,3]; var [a,[[b],c]] = [1,[[2],3]];
如果解构不成功,变量的值就等于undefined。解构赋值适用于var、let和const。
解构赋值不能对undefined和null进行解构,会出现错误。
对象的解构赋值
var {a,b} = {a:"aaa",b:"bbb"}; console.log(a);//"aaa" console.log(b);//"bbb"
对象解构是根据键名来赋值,即使是顺序不同也能够正确赋值。例如:
var {b,a} = {a:"aaa",b:"bbb"}; console.log(a);//"aaa" console.log(b);//"bbb"
若不存在的键名则赋值为undefined。
var {c} = {a:"aaa",b:"bbb"}; console.log(c);//undefined
如果一个已经声明的变量用于解构赋值,需要注意:
//错误的写法 var a; {a} = {a:"aaa"}; //正确的写法 var a; ({a}) = {a:"aaa"}; //或者 ({a} = {a:"aaa"});
由于javascript会将{}解析为代码块,从而赋值时出现错误。可以使用()来解决该问题。
数组新特性
Array的方法拓展
Array.from():将类数组对象和可遍历的对象转化为真正的数组。
可接受第二个参数,用于对每一个成员进行处理。例如:
Array.from(myarr,x => x*x); //等同于 Array.from(myarr).map(x=>x*x);
Array.of():将一组数值转化为数组。
弥补了构造函数Array的不足。例如:
var arr1 = Array(3);//[undefined,undefined,undefined] var arr2 = Array.of(3);//[3]
Array.observe():监听数组的变化;
Array.unObserve():取消监听数组的变化。
变化包括:add、update、delete、splice。
数组实例的方法拓展
find():查找第一个符合条件的数组元素并返回,没有则返回undefined;
findIndex():查找第一个符合条件的数组元素的下标,没有则返回-1。
回调函数接受三个参数包括当前的值、当前的位置、数组。
这两种方法都可以查找NaN。
fill():用给定的值来填充数组
接受的第二、三个参数分别表示填充的起始位置和结束位置。
keys():对键名的遍历;
values():对值的遍历;
entries():对数组元素的遍历。
数组推导
数组推导指的是通过原有数组快速生成新数组,例如:
var arr1 = [1,2,3,4,5]; var arr2 = [for(i of arr1) i*i];//[1,4,9,16,25] var arr3 = [for(i of arr1) if(i<4) i*i];//[1,4,9]
特点:
可以使用多个if语句;
可以使用多个for-of循环;
可以用来推导字符串而产生新的字符串;
新数组立即在内存中生成,可能会耗费较大的内存。
对象新特性
新增方法
Object.is():用于判断两个值是否严格相等。与“===”类似。区别在于:
+0 === -0//true Object.is(+0,-0);//false NaN === NaN//false Object.is(NaN,NaN);//true
Object.assign():将后面的对象内部所有可枚举属性复制到第一个变量所代表的源对象。
注意:
参数至少两个,且必须是对象;
同名的属性,后面的属性值覆盖前面的值。
Object.setPrototypeOf():用于设置一个对象的prototype对象,参数为目标对象以及原型对象;
Object.getPrototypeOf():用于获取一个对象的prototype对象。
对象新写法
ES6定义了对象的新写法。可以直接将变量和函数作为对象的属性和方法,不再严格使用键值对来定义。例如:
var age = 22; var Person = { name : "gjw", age, toString(){ return this.name + " is " + this.age + " years old."; } };
ES6可以使用表达式作为对象的属性名进行定义,需要把表达式放在方括号内,例如:
var name = 'your'; var Person = { [name] : "gjw", age : 22 }; console.log(Person[name]);//"gjw" console.log(Person['your']);//"gjw"
Symbol
ES6新增了一个原始数据类型Symbol,可以通过Symbol()函数来声明,该函数可以接收一个参数作为变量的name属性,例如:
var mySymbol = Symbol('mine'); console.log(mySymbol.name);//mine
注意:
Symbol不能使用new来声明;
每一个Symbol变量都是不同的;
Symbol作为属性名时可以遍历,通过Object.getOwnPropertySymbol()和Object.getOwnPropertyKeys()来获取该属性。
Proxy
ES6提供一个原生的Proxy构造函数,用于设立一个拦截网,在访问对象时,需要先通过这个拦截网。例如:
var Person = { name : "gjw" }; var myProxy = new Proxy(Person,{ get : function(target,property){ if(property in target){ return target[property]; }else{ return "Property " + property + " does not exist."; } } }); console.log(myProxy.name);//"gjw" console.log(myProxy.age);//"Property age does not exist."
结果如下:
函数新特性
函数默认参数
ES6可以为函数参数设置默认值,例如:
function add(a=1,b=1){ return a+b; } var sum1 = add(); var sum2 = add(2,3); console.log(sum1);//2 console.log(sum2);//5
… 的作用
函数传参是可以使用“… 变量名”的形式传进多余的参数。例如:
function add(...values){ let sum = 0; for(var item of values){ sum = sum + item; } return sum; } console.log(add(1,3,5,7,9));//25
注意:
“… 变量名”只能放在最后一个参数,否则会报错。
另外,“…”可以将一个数组解析成一个用逗号隔开的参数序列,例如:
//ES5 Math.max.apply(null,[42,12,23]); //ES6 Math.max(...[42,12,23]);
代码将一个数组传入Math.max函数求最大值,不再需要调用apply等函数来修改参数。
”…变量名“以及”…“可以看做两个互逆运算,一个用于函数定义保存多余参数,一个则是调用时将数组转化为参数序列传入。
箭头函数
ES6可以使用=>来定义函数,例如:
//ES6 var sum1 = (a,b)=>a+b; //正常函数写法 var sum2 = function(a,b){ return a+b; }
注意:
不能当做构造函数,否则会报错;
不能使用arguments对象,因为该对象在函数体内不存在;
this关键字指向定义时所在的对象,而不是使用时所在的对象。
字符串新特性
新增方法
codePointAt:用于处理4个字节储存的字符(Unicode大于0xFFFF的字符),返回一个字符的Unicode编号。
String.fromCodePoint:与codePointAt正好相反,根据一个Unicode返回一个字符。
contains():是否找到参数字符串;
startsWith():返回布尔值,表示字符串是否以参数字符串开头;
endsWith():返回布尔值,表示字符串是否以参数字符串结尾。
该三个函数都可以传入第三个参数,表示查询的位置,不同的是,endsWith()针对前n个进行查询,而contains()和startsWith()则是从n开始向后查询。
repeat():返回一个字符串,表示将源字符串重复n次。
正则修正
u修饰符ES6添加u修饰符来处理大于0xFFFF的Unicode字符。例如:
var s = "??";//显示不出来,可见图示 console.log(/^.$/.test(s)); console.log(/^.$/u.test(s));
结果如下:
如果不添加u修饰符,正则表达式会误以为有两个字符,而导致匹配失败。
2. y修饰符
与g修饰符类似,后一次匹配从上一次匹配成功的下一个位置开始。不同之处在于g修饰符只确保剩下的字符串中存在匹配就行,而y修饰符则必须确保从剩余的第一个位置开始存在匹配才行。例如:
var s = "abcddabder"; var reg1 = /ab/g; var reg2 = /ab/y; console.log(reg1.exec(s));//["ab"] console.log(reg2.exec(s));//["ab"] console.log(reg1.exec(s));//["ab"] console.log(reg2.exec(s));//null
运行结果如下:
意味着y修饰符自带头不匹配标志^。
模块字符串
模块字符串用反引号(`)进行标识。用法可以是声明普通字符串、定义多行或在字符串中嵌入变量。例如:
//普通字符串 `zhe jiu shi yige putong de zifuchuan`; //多行字符串 `zhe shi yige huanhang de zifuchuan`; //字符串中嵌入变量 var name = 'gjw',age = '22'; console.log(`${name} is ${age} years old.`);
数字新特性
新增方法
Number.isFinite():用于判断一个数值是否为数值;
Number.isNaN():用于判断一个数值是否为NaN。
两者与之前的isFinite和isNaN的区别在于新增的函数只对数值有效,不进行隐式的类型转换。
Number.parseInt():函数并没有变化,而是移植到Number对象上。
Number.parseFloat():函数并没有变化,而是移植到Number对象上。
Number.isInteger():判断一个数值是否为整数,其中3和3.0为同一个值。
Number.isSafeInteger():判断一个整数是否为安全整数范围内。
整数范围为-2^53 ~ 2^53。可以使用Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER来表示上下界。
Math.trunc():用于去除小数部分,返回整数部分。
其中还包括很多Math数学方法,在此就不一一列举了。
二进制和八进制表示法
ES6分别使用0b和0o来表示二进制和八进制。