ES6语法整理

ES6

1 let关键字和const关键字

let关键字

①作用

声明变量,用来代替var。let声明的变量具备变量的基本特征

let 变量名=

②特点

  1. let声明的变量不能重复声明

  2. let声明的变量不会变量提升

  3. let声明的变量不会再作为顶层全局的属性

  4. let声明的变量在全局作用域和局部作用域的基础上新增了块级作用域

块级作用域

产生块级作用域的语法:

// 1. {} 语法
{
   语句;
}

// 2. for / while 循环结构
for () {
   
}
while () {
   
}

// 3. if / else / switch 分支结构
if () {
   
} else {
   
}

switch () {
       
}

// 4 try catch
try {
   
} catch ();

const关键字

作用

用于定义常量,常量的特点是值不能修改。
为了与变量区分,一般常量名一般采用全部大写(潜规则)

特点

  1. const声明的常量,不能重新赋值也不能重新声明

  2. 全局变量不会作为顶层全局对象的属性值

  3. 变量不会提升

  4. 常量在全局作用域和局部作用域的基础上新增了块级作用域

数组解构赋值

//变量声明赋值
let [a,b,c]=[1,2,3];
//变量赋值
[a,b,c]=[5,6,7];
// 解构赋值可以有默认值
let [d,e,f=300]=[433,45];
//数组解构可以是直接量也可以是变量
let arr=[5,6,4,3];
let[aa,bb,cc]=arr;

注意:

1. 数组解构赋值本质是按照索引进行解构的
  1. 等号右边必须是数组或者伪数组(具有索引结构的),否则报错

对象解构赋值

//对象解构赋值,按照属性名进行匹配
let {name:'username',age:'userage'}={name:'anni',age:100};
//得到username='anni',age=100,属性名不是变量



//属性名和变量名相同则可以简写
let {a,b}={a:55,b:'anni'}

//变量名可以有默认值
let {c, d=100}={c:89}

一切皆对象,一切都可以作为对象解构赋值(除了null和undefined)

对象解构赋值不需要按照索引,只要有属性就可以

解构赋值用于传参

解构赋值可以用于变量声明时赋值或者修改赋值;也可以给形参传值

//数组的解构赋值
function giao([a,b]){
   console.log(a+b);
}
giao([100,200]);//300


//对象解构赋值
function woligiao({name,age,address}){
   console.log(name,age,address);
}

woligiao({name:'anni',age:99,address:'上海'});

解构赋值应用场景

① 交换两个变量的值

let [a,b]=[5,6];
[a,b]=[b,a]

字符串新增特性

模板字符串

① 定义

使用反引号声明的字符串,称为模板字符串

模板字符串适合内容较多,且需要嵌套很多变量的字符串

//定义变量
let [msg1,msg2]=['are you ok','i am fine'];
//模板字符串
let html=`
<ul>
<li>${msg1}</li>
<li>${msg2}</li>
<li>${100+200}</li>
</ul>
`

②特性

  1. 在模板字符串中换行会作为字符串内容

  2. 模板字符串可以使用${}嵌入变量,表达式都可以嵌入到模板字符串中

其他特性与单双引号字符串一致

字符串实例新增方法

ES3方法:
indexOf() 返回参数在字符串中的位置
lastIndexOf()
toUpperCase()
toLowerCase()
slice()
subString()
subStr()
split()
charCodeAt()
ES5方法:
trim() 去除字符串两边的空格,全是空格的字符串会转换为空字符串

ES6+方法:
repeat() 字符串重复
includes() 判断字符串中是否包含某个值,返回布尔值;第二个参数可以指定查找开始的位置
startsWith()判断字符串是否以某个值开头,返回布尔值;第二个参数指定开始查找的位置
endsWith() 判断字符串是否以某个值结束,返回布尔值;第二个参数指定字符串查找的长度
padStart() 将字符串补充到指定的长度,在前面添加,第一个参数指定总长度,第二个参数指定填充内容(ES2017)
padEnd() 将指定字符串补充到指定长度,将填充内容添加到后面,第一个参数是指定总长度,第二个参数指定填充内容(ES2017)
trimStart()删除字符串左边的空格(ES2019)
trimEnd()删除字符串右边的空格(ES2019)

数值新增特性

新增二进制和八进制表示方法

let num1 = 0b101;//二进制表示方法
let num2 = 0o101;//八进制表示方法

Number 构造函数本身新增方法和属性

ES3属性:
Number.MAX_VALUE
Number.MIN_VALUE

ES6属性和方法:
Number.isNaN() 同全局属性isNaN()
Number.isFinit() 同全局函数 isFinite()
Number.parseInt() 同全局函数 parseInt()
Number.parseFloat() 同全局函数 parseFloat()
Number.isInteger() 判断是否是整数,返回布尔值
Number.isSafeInteger()判断是否是安全整数
Number.MAX_SAFE_Integer 返回最大安全整数
Number.MIN_SAFE_Integer 返回最小安全整数
Number.EPSILON 返回JS的最小精度

安全整数:

在 -2^53 到 2^53 之间的整数称之为安全整数, 不存在计算精度问题。超出该范围的数字计算存在精度问题。

Math新增方法

ES3属性方法:
Math.PI
Math.abs()
Math.sqrt()
Math.pow()
Math.round()
Math.floor()
Math.ceil()
Math.random()
Math.max()
Math.min()


ES 6新增方法:
Math.trunc() 截取数字的整数部分,类似于parseInt()
Math.sign() 参数是正数返回1,参数是负数返回-1,参数等于0返回0,参数是NaN返回NaN
Math.hypot() 求所有参数的平方和的平方根

指数运算符

console.log(3**3);   //27

新增原始数据类型bigint

如果要进行计算的数字超过安全整数的范围,还想保证精度的话,可以定义成 bigint 类型。

bigint 类型用于对大的整数进行计算。

bitint 类型是原始类型,使用 typeof 判断返回 bigint

 // 定义 bigint 类型的数据
let n1 = 100n;
console.log(n1);
console.log(typeof n1);  // bigint
console.log('');

// bigint 类型数据只能与 bigint 类型数据进行数学计算
console.log(n1 + 40n);
// console.log(n1 * 3); // 报错
console.log('');


// bigint 类型数据可以与number类型比较,自动类型转换
console.log(n1 === 100); // false
console.log(n1 == 100);  // true
console.log(n1 > 40);  // true
console.log(n1 > 400); // false
console.log('');


// 也有 二进制方式 八进制方式 十六进制方式
let n2 = 0b101n;
let n3 = 0o101n;
let n4 = 0x101n;
console.log(n2, n3, n4);

 

函数新增特性

函数参数的默认值

ES6允许为函数的参数设置默认值,即直接写在参数的最后面

function fun(name,age=100){
   console.log(name,age);
}

fun('姬发');// 姬发 100
fun('姬发',50)//姬发 50

rest参数

ES6引入rest参数(形式为...变量名),用于获取函数的多余参数,用来代替arguments对象

rest参数搭配的变量是一个数组,将多余的参数放到数组中

//计算所有参数之和
let getSum=(...nums)=>{
   let sum=0;
   nums.forEach(item=>{
       sum+=item;
  });
   return sum;
}
console.log(getSum(4,43,5,6,7));

rest 参数特点:(相比于arguments)

  1. rest参数得到的是纯数组,arguments得到的是伪数组

  2. rest参数获取的是多余的参数,arguments获取的是所有的参数

  3. rest必须写在形参的最后一个,arguments不需要写也直接产生

箭头函数

①语法

//创建有个箭头函数
let fn=(name,age)=>{
   console.log(`我叫${name},我今年${age}岁`)
};

//调用函数
fn('gmy','23');

箭头函数简略写法:

  1. 省略()的条件:只有一个参数,多个参数或者没有参数都不能省略。

  2. 省略{}的条件:函数体内只有一条返回值语句,省略{}和return

②箭头函数的特点

  1. 箭头函数没有自己的this,会取上层作用域的this;因此箭头函数中的this与调用者无关,只与箭头函数声明的地方有关

  2. 箭头函数没有arguments但是可以有rest参数

  3. 箭头函数不可以作为构造函数,new则报错

  4. 箭头函数不能使用yield,无法创建生成器函数

函数参数尾逗号(ES2017)沙雕行为

函数的最后一个参数后面可以添加尾逗号,不论报错!

不论是函数声明还是函数调用,都可以加尾逗号。

function fn(name, age, ) {
   console.log(name, age);
}
fn('安妮', 109);
fn('安妮', 108, );


// ES5 中就已经允许对象的尾逗号
let obj = {
   name: '曹操',
   age: 100,
};

 

数组的新特性

①扩展运算符

扩展(spread)运算符是三个点 ... 。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

不但可以拆解纯数组,伪数组也可以被拆解。

function fun(a,b,c){
   console.log(a,b,c,a+b+c);
   
}
var nums=[100,200,300,250];

fun(nums)//输出[100,200,300,250],undefined,undefined,100,200,300,250undefinedundefined

fun(...nums)//输出100,200,300,600

②扩展运算符的应用场景

1)用于函数传参
//1.函数传参
let arr = [123,54,65,324];
//获取最大值
console.log(Math.max(...arr));
2)复制数组
let arr=[789,534,54,234];
var arr2=[...arr];
//解决了引用数据类型的问题
3)合并数组
let arr1=[43,54,56];
let arr2=[24,6,234];
var arr3=[...arr1,...arr2];
4)把类数组转换为纯数组
var arr=[...document.all];
var ary=[...'hello world']

rest 元素

扩展运算符用于数组解构赋值, rest 元素对应的变量获取由剩下的值组成的数组。

rest 必须放在最后,本质与 rest 参数是一致的。

// 数组解构赋值
let [first, ...seconds] = [10, 20, 30, 40, 50];

console.log(first);  // 10
console.log(seconds); // [20, 30, 40, 50];

Array构造函数本身新增的方法

ES6新增方法:
Array.from() 把伪数组转换为纯数组
Array.of() 创建新数组,参数会作为数组中的元素,可以设置任意量的参数,基本可以用来代替Array()和new Array()

Array实例新增方法

ES3:
	length
	join()
	slice()
	push()
	pop()
	unshift()
	shift()
	concat()
	splice()
	reverse()
	sort()
	
ES5:
	indexOf()
	lastIndexOf()
	forEach()
	filter()
	map()
	some()
	every()
	reduce()
	reduceRight()
	
ES6:
	find(callback)	返回数组中第一个满足条件的元素,参数是回调函数,回调函数接受元素和索引,回调函数返回true表示条件满足
	findIndex(callback)	返回数组中第一个满足条件的参数的索引,参数是回调函数,回调函数接受元素和索引,回调函数返回true表示条件满足
	fill(val [,start][,end])	用于填充数组,把数组中的指定元素替换为val,后两个参数不填则替换全部
	entries()	返回由数组的索引和值构成的遍历器对象
	keys()	返回由数组的索引组成的遍历器对象
	values()	返回右数组的值组成的遍历器对象
	includes(val)	判断数组中是否包含指定值,返回布尔值(可以判断NaN)
	flat(num)	用于拉平数组(把多维数组转换为一维数组),参数可以指定拉多少层,默认是1,可以设置参数为Infinity(拉平任意维数组)
	filterMap()	先对数组Map处理再进行flat操作,只能拉平一层
	

 

对象新特性

对象声明时候的简写

如果属性的值用变量来表示,恰好属性名与变量名一致,可以简写

//定义四个变量
let [name,age,address,grade]=['曹操',32,'许昌','魏国'];
//声明函数
function getInfo(){
    console.log('getInfo');
}

//声明对象
let obj={
    name,
    age,
    address,
    getInfo
};

声明对象时方法的简写

//定义对象
let user={
    name:'司马懿',
    age:99,
    aoligei(){
        
	}
}

属性名表达式

ES5 中,在使用属性的时候,如果属性名用变量表示或者属性名不符合标识符规范,可以使用[] 语法。

ES6,在创建对象的时候,也可以用 []来指定属性名,[] 内可以写表达式(变量、直接量、运算表达式),表达式的值会作为属性名。

//声明变量
let prop='address';
//创建对象
let obj={
    [prop]:'上海',
    [1+7]:'丑',
    'user-name':'文丑',
    ['grade']:66
}

super 关键字

  1. supper指向的是方法所在的原型对象,this指向的是调用该方法的对象;

  2. super只与声明时所在的对象有关系,与哪个调用该方法无关

  3. super只能写在声明方法的简写方式中

对象的扩展运算符

扩展运算符如果用于数组,则可以把数组转换为由逗号隔开的参数序列。

扩展运算如果由对象使用,可以把对象转为由逗号隔开的键值对序列。

①对象的扩展运算符的应用场景

  1. 用于对象的复制

  2. 用于对象合并

var obj3={...obj1,...obj2};

②对象的扩展运算符用于对象解构赋值

解构赋值时,变量名前面加扩展运算符,会得到一个对象,带扩展运算符的变量要写在最后面

//用于解构赋值
let {gdx,...df}={name:534,gdx:'ok',ok:54,fls:'fsdj'};
console.log(df);// 得到df为{name: 534, ok: 54, fls: "fsdj"}

Object构造函数本身新增的方法

ES5方法:
	Object.create()	创建一个对象,指定对象的原型
	Object.definedProperty()	添加属性,并指定属性的特性
	Object.definedProperties()	添加多个属性,并指定属性的特性
	Object.getOwnPropertyDescriptor()	获取对象中属性的特性
ES6方法:
	Object.is(arg1,arg2)	用来判断参数是否相等,返回布尔值,与===的区别是,+0和-0不相等,NaN和NaN相等
	Object.assign(target,source1,source2...)	合并对象,把第二个参数开始合并到第一个参数,并返回第一个参数(用于:对象合并,对象复制,对象默认值)
	Object.keys(obj)	返回对象obj中所有属性名的数组集合
	Object.values(obj)	返回obj中所有属性值的数组集合
	Object.entries(obj)	返回对象中所有的属性名和属性值组成的二维数组
	Object.fromEntries()	Object.entries的逆运算
	Object.getOwnPropertyDescriptors()	获取对象中所有的特性信息

 

Object 实例新增的属性

__proto__属性(前后各两个下划线),用来读取或设置当前对象的原型对象。

__proto__前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的 API,只是由于浏览器广泛支持,才被加入了 ES6。

Class语法

使用Class定义类

//定义类 给类设置属性和方法
class User{
    //给实例设置属性,属性添加到实例本身
    name='安妮';
	sex='女';
	//给实例添加方法,添加到实例的原型
	say(){
        console.log(`我叫${this.name},我的性别是${this.sex}`);
    }

}

类的语法特性:

  1. 类的本质还是构造函数,typeof返回function

  2. 类只能用来实例化不能调用

  3. 类中智能定义属性和方法,不能直接使用this(方法中才能写this),不能写其他语句

  4. 类中定义的属性会添加到实例的本身,类中定义的方法会添加到实例的原型上面

类中定义构造器方法

//定义类 给类设置属性和方法
class User{
	name='null';
	age='null';
	address='null';
	
	//定义构造器方法 在实例化的过程中,自动调用
	constructor(name,age,address){
		//给属性赋值
        this.name=name;
        this.age=age;
        this.address=address;
    }
	//给实例设置方法
	say(){
        console.log(`我叫${this.name},今年${this.age}岁,住在${this.address}`);
    }
}


//实例化
let u1=new User('曹操',99,'许昌 ');
let u2=new User('刘备',99,'汕头')

构造器方法在类被实例化的时候,会自动调用;可以接受类名后面()里的参数。

构造器方法中的 this 指向实例。

一般用于实例化的时候为属性赋值。

静态方法

在类中的方法前面加static关键字,就表示该方法不会添加到实例的原型上,而是添加到实例的本身,被称为静态方法

class Foo{
    static classMethod(){
        return 'hello';
    }
}

属性名前面添加static,也会创建属性,(类的本身属性)非标准

访问器属性

//创建类
class Person{
    //定义属性
    firstName=null;
	lastName=null;
	
	//构造器方法
	constructor(firstName,lastName){
		this.firstName=firstName;
        this.lastName=lastName;
    }
	//访问器属性 读取
	get fullName(){
        return this.firstName+'·'this.lastName;
    }

	//访问器属性 设置
	set fullName(val){
        if(val.includes('·')){
            this.firstName=val.split('·')[0];
            this.lastName=val.split('·')[1];
        }
    }
}

实现继承

使用关键字extends继承

//定义父类
class Animal{
    //设置属性
    color:null;
	weight:null;
	//吃
	eat(){
        console.log('我是动物我会吃');
    }
}

//定义子类
class Person extends Animal{
    name=null;
	say(){
		console.log(`我叫${this.name}, 我的肤色是${this.color}, 我的重量是${this.weight}`);
    }
}

子类继承了父类之后,子类的实例,不但可以使用自己的类定义的属性和方法,还可以使用父类上定义的属性和方法。

单继承:一个父类可以有多个子类,但是一个子类只能有一个父类。

继承的原理: 子类实例的原型指向父类的一个实例。

方法和属性的重写

子类如果定义了与父类重名的属性和方法,会重写

super关键字

子类如果重写构造器方法,必须在里面用super()调用父类的构造器方法。

子类重写构造器方法只能增量修改

super()只能在子类构造器方法中调用,且必须写在最前面

 // 定义子类
class Person extends Animal {
    // 设置属性
    name = null;

    // 重写父类的构造器方法 
    constructor(name, color, weight) {
        // 调用super() 相当于调用父类的构造器方法
        super(color, weight);
        this.name = name;
    }

}

继承系统类(内置的构造函数)

允许子类继承系统内置的类(Array、Function、Object ...),继承内置类的特性。

 // 声明类
class MyArray extends Array {
    // 重写构造器方法
    constructor(...args) {
        super(...args);
    }
}

新增元素数据类型Symbol

1)Symbol 是 JavaScript 新增的一种原始类型数据,typeof 会返回 symbol

2)通过调用 Symbol() 可以创建 Symbol 类型的数据,注意, Symbol 只能调用不能实例化。

3)每创建一个 symbol 类型的数据,都是唯一的。其实,对象类型的数据,每创建一个实例也都是唯一了,而 symbol 作为一个原始类型,具有了对象类型的这一个特点。

4)Symbol 类型的数据可以作为对象的属性名。

新增数据类型Set和Map

set

①Set数据类型

ES6新增的数据类型,跟数组类型相似,是值的集合,但是不能重复

值可以是任意类型

②Set构造函数

set函数可以接受一个数组(或者具有iterable接口的其他数据解构)作为参数,用来初始化。

//创建Set数据
const s=new Set([1,3,4,5]);
//将set转换为数组
var arr=[...s];

③Set实例的方法/属性

add()	添加一个值
delete()	删除一个值
has()	判断是否包含某个值,返回布尔值
clear()	清空Set所有值
forEach()	遍历
keys()	返回遍历器对象
values()	返回遍历器对象
entries()	返回遍历器对象

size		得到长度(类似于数组的length)

④利用Set结构数组去重

let arr=[5,6,4,5,6];
let newArr=[...new Set(arr)];

WeakSet

①WeakSet数据类型

WeakSet结构与Set类似,也是不重复的值的集合,但是它与Set有两个区别:

1)首先,WeakSet成员只能是对象

2)WeakSet不可遍历

②WeakSet构造函数

作为构造函数,WeakSet可以接受一个数组(或者其他可遍历对象)作为参数。该数组的所有成员,都会自动成为WeakSet的实例对象的成员

作为参数的数组(或者具有 iterable 接口的其他数据结构)的成员只能是对象。

③WeakSet实例的方法

add(val)
delete(val)
has(val)

Map

①Map类型数据

类似于对象,也是键值对的集合,但是“键”的范围不限于字符串各种类型的值(包括对象)都可以当做键。

②Map构造函数

任何具有iterator接口、且每个成员都是一个双元素的数据结构(数组和可遍历对象)都可以当做Map构造函数的参数

//用二维数组作为参数
let map=new Map([
    [1,2],
    ['ok','fine'],
    [{name:'anni'},1]
]);

//用Set数据结构作为参数
let set=new Set([
    ['shit','bol'],
    [name,'曹操']
]);
let map1=new Map(set);

③Map实例的方法

get(key)	根据key获取值
set(key,val)	根据key设置值
has(key)	判断是否存在指定的key
delete(key)	删除对应的key和value
clear()		清除所有的键值对
keys()	获取所有的key组成的遍历器对象
values()获取所有的value组成的遍历器对象
entries()	获取所有的键值对组成的遍历器对象
forEach(callback)用于遍历
size属性,获取键值对的数量

 

WeakMap

① WeakMap 数据类型

WeakMap结构与Map结构类似,也是用于生成键值对的集合,WeakMap 与Map 的区别有两点:

1)WeakMap只接受对象(所有的对象类型,除了原始类型)作为键名,不接受其他类型的值作为键名。

2)不可遍历。

② WeakMap 构造函数

// WeakMap 可以使用 set 方法添加成员
const wm1 = new WeakMap();
const key = {foo: 1};
wm1.set(key, 2);
wm1.get(key) // 2

// WeakMap 也可以接受一个数组,
// 作为构造函数的参数
const k1 = [1, 2, 3];
const k2 = [4, 5, 6];
const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
wm2.get(k2) // "bar"

③ WeakMap 实例的方法

set(key, value)
get(key)
has(key)
delete(key)

Iterator遍历器对象和可遍历对象

Iterator遍历器对象

1)iterator(遍历器)是一种接口,为各种不同数据结构提供统一访问机制,任何数据只要部署Iterator接口,就可以完成遍历操作。

2)每个Iterator(遍历器)都有一个next()方法

3)Iterator遍历器内部存在一个指针,指针指向遍历器的第一个数据,调用next(),会取出指针指向的数据,并且指针下移;

4)每一次调用next()方法,都会返回数据结构的当前成员的信息,具体来说,就是返回包含valuedown两个属性,的对象。其中value属性是当前成员的值,down属性是一个布尔值表示遍历是否结束;

var set = new Set([100,200,300,400]);
var setIterator=set.keys();
let res=null;
do{
    res=setIterator.next();
    if(res.value!==undefined){
        console.log(res.value);
    }
}while(!res.done);

iterable可遍历对象

①什么是可遍历对象

1)吧部署了Iterator(遍历器对象)接口的数据结构称之为iterable(可遍历对象)

2)iterator 接口部署在了数据结构的 Symbol.iterator 属性上,换句话说一个对象,只有具有 Symbol.iterator 属性,且该属性指向一个返回 iterator(遍历器对象) 的函数, 该对象就是 iterable(可遍历对象)。

const obj={
    [Symbol.iterator]:function(){
        return{
            next(){
                return {
                    value:1,
                    done:true
                };
            }
        }
    }
}

②原生实现了Iterator接口的类型(可遍历对象)

Array
Set
Map
String
Arguments
NodeList
HTMLCollection

③ 可遍历对象和遍历器对象的区别和关系

iterator(遍历器对象)也是iterable(可遍历对象);但是,iterable(可遍历对象)不一定是iterator(遍历器对象)。

遍历器对象本身也部署了 iterator 接口。

可遍历对象不一定拥有 next 方法.

④ 可遍历对象和类数组(伪数组)

类数组(伪数组): 对象中有索引结构,有length 属性,就是伪数组。

可遍历对象: 部署了 iterator 接口的对象,才是可遍历对象。

调用可遍历对象Iterator接口的场合

调用Iterator时说明必须使用可遍历对象

数组解构赋值
使用数组扩展运算符
Array.from()
for of遍历
Set	构造函数的参数
WeakSet 构造函数的参数
Map 构造函数的参数
WeakMap 构造函数的参数
Promise.all
Promise.race

for of

for of结构可以用来遍历对象(包括遍历器对象),在遍历可遍历对象的时候自动调用Iterator接口

var  arr=['red', 'green', 'blue'];
for(let k of arr ){
    console.log(k);	//red', 'green', 'blue'
}

生成器generator

定义

生成器就是能创建遍历器的函数

如何定义

function* gen(){
	
}
typeof gen;		//function
let iter=gen();

调用生成器函数无论里面有没有return,都会返回一个遍历器对象

yield关键字

1)yield关键字返回一个值,遍历的时候每次得到的就是yield的值

2)调用next(),执行到yield就会停止,下次调用next(),执行到下一个yield停止

调用生成器函数时,函数内部代码不会执行,只有调用next()方法的时候才开始执行内部代码,执行到以yield停止

function* gener(){
    yield 值;
    yield 值;
    yield 值;
    yield 值;
}

return 可以终止生成器遍历

利用生成器对象部署Iterator接口

//创建obj对象
var obj={
     name: '安妮',
    age: 89,
    address: '上海',
    //部署Iterator接口
    [Symbol.iterator]:function*(){
        for(var k in obj){
            yield [i, obj[i]]
        }
    }
}

模块(module)

定义模块

//module1.js
export var firstName='anni';
export function say(){
    console.log('hello world');
}
//module2.js
var user='典韦';
function skill(){
    console.log('奥利给');
}
export default{
    user,
    skill
}
    

 

模块导入

//导入模块一
import {firstName,say} from 'module1.js'
//使用导入的变量、函数
console.log(firstName);
say();
//导入模块二
import myMo from 'moudule.js'
//以对象形式传入
myMo.user;
myMo.skill();

新增的运算符 (ES2020)

可选链运算符 ?.

可选链运算符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。

?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

当尝试访问可能不存在的对象属性时,可选链操作符将会使表达式更短、更简明。

用于调用对象属性的属性的时候,链式调用

// 使用对象属性的属性,需要现判断对象的属性是否存在

// 如果 obj 中没有 users 属性,会报错!!!!!
if (obj.users.age) {
    
}

// 使用嵌套方式避免报错
if (obj.usrs) {
    if (obj.users.age) {
        
    }
}

// 使用 && 避免报错
if (obj.users && obj.users.age) {
    
}

// 使用可选链运算 推荐!!!!!!!!! 牛逼!!!!!!!!!!!!!!
if (obj.users?.age) {
	    
}
// 如果 obj 下没有 getInfo 方法,会报错
obj.getInfo();

// 即使 obj 下没有 getInfo 方法,也不会报错!
obj.getInfo?.();

 

空值合并运算符??

空值合并运算符??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

与逻辑或运算符符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如,''0)时。

console.log(null ?? 2000);  // 2000
console.log(undefined ?? 2000);  // 2000
console.log(false ?? 2000);  // false
console.log(0 ?? 2000);  // 0
console.log('' ?? 2000);  // 空字符串
console.log(NaN ?? 2000);   // NaN

 

posted @ 2020-11-24 21:18  新成  阅读(1294)  评论(0编辑  收藏  举报