es6,es7,es8语法总结
es6部分
1.let,const
let,const具有块级作用域,不具有变量提升(let用法和var一样,但有区别)
(1)let用法:
1.不会变量提升
2.遇到{} 里面let定义的变量就会变成块级作用域,拿不到里面的值
块级作用域例子
function fn(){
let num = 5;
if(true){
let num = 10;
}
console.log(num);//获取到的结果还是5,因为if里面有{},let无法获取里面let=10的值
}
(2)const用法
const定义的都是常量,不能在改变值
const PI = 3.1425;
PI = 2;
console.log(PI)//输出结果3.1425
2. 箭头函数
我们经常要给回调函数给一个父级的this
常用办法就是 var self = this 定义一个变量接住他
使用 箭头函数,this 将不会受到影响,可以直接用this调用父级的this
箭头函数的写法和用法:
第一种:对于只有一个形参和一个返回值的情况下,这里的V代表形参和返回值
Es5写法:
function fn(v){
return v;
}
fn(3);
Es6写法:
var fn = v => v;
var res = fn(3);
console.log(res);
第二种:没有形参时,箭头函数加上()代表空形参;
Es5写法:function fn(){
return 6;
}
fn();
Es6写法:
var fn = () => 6;
var res = fn();
console.log(res)
第三种:形参为两个时,需要加上(形参1,形参2)
Es5写法:
function fn(num1,num2){
return num1 + num2
}
fn(3,4);
Es6写法:
var fn = (num1,num2) => num1 + num2;
var res = fn(2,3);
console.log(res);
第四种:两个形参,且函数有多个内容,以及多个返回值时
Es5写法:
function fn(num1,num2){
console.log(1);
console.log(2);
return num1 + num2;
}
Es6写法:
var fn = (num1,num2) => { //多余一条语句 语句要放在 {}里,如果还行有返回值,那么要加return才可以
console.log(1);
console.log(2);
return num1 + num2;
}
var res = fn(5,4);
console.log(res)
第五种:函数里面的返回值是一个对象时,返回值需要用()包起来,原来的对象还得需要加上{}
Es5写法:
function fn(name,age){
return {
uname : name,
uage : age
}
}
var res = fn('jack',16);
console.log(res)
Es6写法:
var fn = (name,age) => ({uname : name,uage : age});
var res = fn('jack',13);
console.log(res);
3. 字符串
includes:
const string = 'food';
const substring = 'foo';
console.log(string.includes(substring));
返回的是布尔值。
string.repeat(str,count)
如果 string.length < count 即插入str到count == string.length为止
4. 模板字符串: `` 遇到变量: ${变量}
Es6的字符串拼接方法:
var obj = {uname:"jack",age:8}
var str = `姓名:${obj.uname}年龄:${obj.age}
`;
document.body.innerHTML =str;
Es5的字符串拼接方法:
var obj = {uname:"jack",age:8}
var str ='姓名:'+obj.uname+'年龄: '+obj.age+'
';
document.body.innerHTML =str;
5.解构
结构数组:
一.数组的取值法
1.数组求值写法:
Es6的数组求值方法:
var arr = [4,2,32];
var [a,b,c] = arr;
console.log(a,b,c);//新的求数组的每一项的方法,输出结果是4,2,3
Es5的数组求值方法:
var arr = [4,2,32];
var a = arr[0];
var b = arr[1];
var c = arr[2];
var d = arr[3];
console.log(a,b,c,d);输出结果是4,2,3
2.数组默认值:
var ary = ["lily",34]
let [name,age=16] = ary;
console.log(name,age);//输出结果是 lily ,34
var ary = ["lily"]
let [name,age=16] = ary;
console.log(name,age);//输出结果是 lily ,16
分析:age变量的取值先看数组ary中有没有对应的值,如果有,取数组里面的值34,如果没有取默认值16
结构对象:
Es6的对象求值新方法:
let {uname : name1, age : age1} = obj ;
console.log(name1,age1);//输出结果:jack,10
特殊:变量名和 属性名一样了;可以把属性名省略
let {uname : uname , age : age} = obj;
console.log(uname,age)//输出结果:jack,10
Es5的对象求值方法:
console.log(obj.uname);
console.log(obj.age);
6.对象方法的简写
Es6的对象函数简写:相比较而言,省略了function函数
var obj = {
say(){
alert(1);
},
play(){
alert(2);
}
}obj.play();
Es5的对象函数:
var obj = {
say : function(){
alert(1);
},
play : function(){
alert(2);
}
}
obj.play();
7.rest参数
处理不定数目参数:
function logArguments(...args) {
for (let arg of args) {
console.log(arg);
}
}
8.归并和扩展运动符
(1)assign用法:
objct.assign()方法 归并
objct.assign(target,a,b,c);就是把三个对象归并到target目标对象里面
var target = {pid:1};
var a ={pnam:"华为"};
var b ={price:1200};
var b = {pid:10}
console.log(Objctassign(target,a,b,c))
(2)扩展运算符 ...
var obj1 = {name:"lily",age:18};
var obj2 = {...obj1};
console.log(obj2);
//输出结果是:
age: 18
name: "lily"
console.log(Object.assign({},{name : "lily"},{age : 18}))
console.log(obj2);
/输出结果是:
age: 18
name: "lily"
扩展运算符和assign()用法很像
9.构造函数:
Es5构造函数方法
function Animal(){ // 构造函数中的this否是实例
this.color = "白色";
this.age = 8;
this.say = function(){
}
}
var res = new Animal(); // 对象(实例) 一个属性 方法
console.log(res)*/
Es6构造函数方法
class Animal{//class开头
constructor(){//用的对象简写
this.age = 5;
this.color = "黑色"
}
}
var res = new Animal();
console.log(res);
注意:class 定义一个类
属性要放在 constructor里
10.set集合和Map是Es6中提供的新的数据结构
Set类似于数组,但成员的值都是唯一的,数组不能调用它的方法
Set 实例的属性和方法
1.size:所有元素个数(相当于数组中的length)
2.add(value):添加某个值,返回Set结构本身
3.delete(value):删除某个值,返回一个布尔值,表示删除是否成功,删除成功返回true,删除失败返回false
4.has(value):返回一个布尔值,表示该值是否为Set成员
5.clear();清除所有成员,没有返回值
遍历:
6.
(1)forEach():使用回调函数遍历每个数组 数组方法
(2)for of:遍历对象
for(var item of set){
console.log();
}
7.Es6新增的数组方法
Array.from() :将每个集合类数组转成数组
Array.of()
8. map集合map类似于对象,也是键值对的集合, 但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键方法有:
set():设置
get():获取
delete():删除
has():查找
clear():清除所有
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map() 方法按照原始数组元素顺序依次处理元素。
注意: map() 不会对空数组进行检测。
注意: map() 不会改变原始数组。
var map = new Map();
map.set('pid', "华为123");
map.set("price", "120元");
map.set('address' ,"中南海");
案例解析:
(1).Array.from()方法的使用
var set = new Set([5,3,4,5,6,3,4]); // new出来的 都是一个对象,为了让他变成数组,使用
Array.from()
var arr = Array.from(set);
arr.push(8);//变成数组后就可以用数组的方法在后面添加8了
console.log(arr);//输出结果为:[5,3,6,4,8]
(2).add(value)和size的用法
var set = new Set();
set.add(3);
set.add(4);
set.add(6);
set.add(4).add(5).add(7);
console.log(set.size);//相当于数组中的length,输出结果是5
console.log(set);//输出结果是3,4,6,5,7,说明Set方法可以去重复
(3).delete和has(value)和clear()
set.delete(4);
console.log(set.has(4));
set.clear();
console.log(set)
(4).set.forEach()
set.forEach(function(item,index,set1){
console.log(item) // 注意 : set是一个集合 index 和 item是一样的
console.log(set1)
})
(5).链式写法
arr.slice(1,3) 返回来的还是 数组,所以可以继续调用push方法
var arr = [4,23,2,36,7];
arr.slice(1,3).push(5);
11.Promises 链式调用
func1(value1)
.then(func2)
.then(func3)
.then(func4)
.then(func5, value5 => {
});
12.Generators 用同步的代码风格来写异步代码
function* genFunc() {
// (A)
console.log('First');
yield; //(B)
console.log('Second'); //(C)
}
ES7部分(新增的两个)
Array.prototype.includes 它是一个替代indexOf,开发人员用来检查数组中是否存在值,indexOf是一种尴尬的使用,因为它返回一个元素在数组中的位置或者-1当这样的元素不能被找到的情况下。所以它返回一个数字,而不是一个布尔值。开发人员需要实施额外的检查。在ES6,要检查是否存在值你需要做一些如下图所示小技巧,因为他们没有匹配到值,Array.prototype.indexOf返回-1变成了true(转换成true),但是当匹配的元素为0位置时候,该数组包含元素,却变成了false。
includes也可以在NaN(非数字)使用。最后 ,includes第二可选参数fromIndex,这对于优化是有好处的,因为它允许从特定位置开始寻找匹配。
1. includes
案例1:
代码:
let array = ['1','2','3']
if(array.includes('2')){
console.log('有')
}
案例2:
console.log([1, 2, 3].includes(2)) // === true)
console.log([1, 2, 3].includes(4)) // === false)
console.log([1, 2, NaN].includes(NaN)) // === true)
console.log([1, 2, -0].includes(+0)) // === true)
console.log([1, 2, +0].includes(-0)) // === true)
console.log(['a', 'b', 'c'].includes('a')) // === true)
console.log(['a', 'b', 'c'].includes('a', 1)) // === false)
2. 指数操作符
案例:2**3 == 8
案例2:
let a = 7 ** 12
let b = 2 ** 7
console.log(a === Math.pow(7,12)) // true
console.log(b === Math.pow(2,7)) // true
开发者还可以操作结果:
ES8部分
1. object.entries()
案例1代码:
let obj = {a: 1, b: 2, c: 3};
Object.entries(obj).forEach(([key, value]) =>{
console.log(key + ": " + value); // 输出a: 1, b: 2, c: 3
})
案例2代码:
//·Object.entries·将会返回对象自身可迭代属性key-value对数组(作为一个数组),他们(key-value)分别以数组存放数组中:
let obj = {a: 1, b: 2, c: 3}
JSON.stringify(Object.entries(obj))
"[["a",1],["b",2],["c",3]]"
案例3代码:
let obj = {a: 1, b: 2, c: 3}
for (let [key, value] of Object.entries(obj)) {
console.log(`${key} is ${value}`)
}
// a is 1, b is 2, c is 3
2.Async Await 异步
异步函数(或者async/await)特性操作是Promise最重要的功能。这种想法是为了在写异步代码中简化它,因为人类大脑最讨厌这种平行非序号思维了。它只是不会演变这种方式。本来以为Promise的到来已经是摆脱node异步的福音了,在ES8,异步函数是那么给力。开发者定义一个asyc函数里面不包含或者包含await 基于Promise异步操作。在这引擎之下一个异步函数返回一个Promise,无论无何你在任何地方不会看到这样的一个词Promise。
案例1
代码:
async fetchData(query) =>{
try {
const response = await axios.get(`/q?query=${query}`);
const data = response.data;
return data;
}
catch (error) {
console.log(error)
}
}
fetchData(query).then(data => {
this.props.processfetchedData(data)
})
3.函数参数列表和调用中的尾逗号(Trailing commas)
尾逗号在函数定义中只是一个纯粹语法变化,在ES8中,这种尾逗号是没有问题的:
案例1
var f = function(a,
b,
c,
d,
) { // COMMA? OK!
// ... console.log(d)
}
f(1,2,3,'this')
案例2
var arr = [1, // Length == 3
2,
3,
] // <--- ok
let obj = {a: 1, // Only 3 properties
b: 2,
c: 3,
} // <--- ok
4.Object.getOwnPropertyDescriptors
这新的 Object.getOwnPropertyDescriptors返回对象obj所有自身属性描述。这是一个多参数版本的Object.getOwnPropertyDescriptors(obj,propName)将会返回obj中propName属性的一个单独描述。
在我们日常不可变编程(immutable programming)时代中,有了这个方法很方便(记住,Javascript中对象是引用传递)在ES5中,开发者要使用Object.assign()来拷贝对象, Object.assign()分配属性只有copy和定义新的属性。当我们使用更加复杂对象和类原型,这可能会出问题。
Object.getOwnPropertyDescriptors允许创建真实的对象浅副本并创建子类,它通过给开发者描述符来做到这一点.在Object.create(prototype, object)放入描述符后,返回一个真正的浅拷贝。
Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
或者可以合并两个对象target和source如下:
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
)
这里有两种描述符号类型:
1.数据描述符(Data descriptor)
2.存取器描述符(Accessor descriptor)
存取描述符有必须属性:get 或者set或者get和set两个就是如你所想的getter和setter函数,然后存取描述符还有可选属性configurable和enumerable
let azatsBooks = {
books: ['React Quickly'],
get latest () {
let numberOfBooks = this.books.length
if (numberOfBooks == 0) return undefined
return this.books[numberOfBooks - 1]
}
}
这个例子数据描述符books由Object.getOwnPropertyDescriptor(azatsBooks, 'books')产生结果如下:
Object
configurable: true
enumerable: true
value: Array[1]
writable: true
__proto__: Object
同样的,Object.getOwnPropertyDescriptor(azatsBooks, 'latest')将会展现latest的描述符,这个latest(get)存取器描述符展现如下:
Object
configurable: truee
numerable: true
get: latest()
set: undefined
__proto__: Object
现在我们调用新方法获取所有的描述符:
console.log(Object.getOwnPropertyDescriptors(azatsBooks))
它会给出这个对象两个描述符books和latest:
Object
books: Object
configurable: true
enumerable: true
value: Array[1]
writable: true
__proto__: Object
latest: Object
configurable: true
enumerable: true
get: latest()
set: undefined
__proto__: Object
__proto__: Object
5.String padding(字符串填充)
String.prototype.padStart 和 String.prototype.padEnd在javascript字符操作是一个不错的体验,帮助避免依赖而外的库。
padStart()在开始部位填充,返回一个给出长度的字符串,填充物给定字符串,把字符串填充到期望的长度。从字符串的左边开始(至少大部分西方语言),一个经典例子是使用空格创建列:
console.log('react'.padStart(10).length) // " react" is 10
console.log('backbone'.padStart(10).length) // " backbone" is 10
它对于财务方面非常有用:
console.log('0.00'.padStart(20))
console.log('10,000.00'.padStart(20))
console.log('250,000.00'.padStart(20))
如果是为会计做账之类的,这个很实用,帐做的很整齐?
0.00
10,000.00
250,000.00
第二个参数,让我们放一些其他的填充字符替代空字符串,一个字符串填充:
console.log('react'.padStart(10, '_')) // "_____react"
console.log('backbone'.padStart(10, '*')) // "**backbone"
padEnd顾名思义就是从字符串的尾端右边开始填充。第二个参数,你能实际上用一个任何长度的字符串。例如:
console.log('react'.padEnd(10, ':-)')) // "react:-):-" is 10
console.log('backbone'.padEnd(10, '*')) // "backbone**" is 10