一、Let和Const
let声明变量,可变
const定义常量(实际指的是变量和的内存地址),不可变
只能在其声明或定义的代码块内有效
注:若区块中存在let或者const命令,则这个区块对这些变量和常量在一开始就行成封闭作用域,只要在声明之前使用就会报错(可能会出现暂时性死区)
不能重复声明,否则报错
(一)块级作用域
闭包:JS中的变量是没有作用域时的一个临时解决方案
块级作用域可以任意嵌套
外层作用域不能访问内层作用域的变量
内层作用域可以定义外层作用域的变量
函数中的块级作用域
es6中在块级作用域中可以声明函数
函数声明的语句和let的行为类似,在块级作用域外不能访问
函数声明也会提到块级作用域的头部
(二)ES6声明变量的6种方式
var
function
let
const
import
class
二、解构赋值
按照一定模式从数组和对象中提取值,然后赋值给变量
如果解构不成功,则变量的值为undefined
不完全解构:等号左边的模式值匹配一部分的等号右边的数组,仍然可以解构成功
解构赋值允指定默认值
默认值可以引起解构的其他变量,但是该变量必须已经声明
(一)对象的解构赋值
数组的元素是按照次序排列的,变量的取值是按照他的位置决定的,而对象没有次序,变量必须与属性同名才能取到正确的值
对象的解构也可以指定默认值,默认值生效的条件是,对象的属性严格的等于undefined
如果解构失败,变量的值就等于undefined
如果解构的模式是嵌套的对象,而且子对象所在的父属性不存在,则会报错
不会复制继承自原对象的属性
(二)字符串的解构赋值
字符串解构赋值时字符串被转换成了一个类似于数组的对象(类似于数组的对象还有一个length属性,也可对其赋值)
(三)数值和布尔的解构赋值
解构赋值时,如果等号右边是数值或者布尔值,则会先转换成为对象,在进行赋值
解构的规则:只要等号的右边不是对象或者数组,都会先将其转换成对象(注:undefined和null无法转换成对象,对其进行赋值时都会报错)
(四)函数的解构赋值
函数参数也可以进行解构,也可使用默认值
(五)圆括号问题
变量声明语句,模式不能使用圆括号(eg:函数的参数)
赋值语句的非模式部分可以使用圆括号
三、字符串的扩展
JS允许使用\uxxxx的形式表示一个字符,xxxx:字符的Unicode码点
在JS内部,字符以UTF-16的格式存储,每个字符固定为2个字节
codePointAt():能正确处理4个节点的字符,并返回一个字符的码点
参数:字符在字符串中的位置
String.fromCharCode():可以识别大于0xFFFF的字符
参数:大于0xFFFF的字符
at():可以识别Unicode编号大于0xFFFF的字符,返回正确的字符
参数:
normalize():将字符的不同表示方法表示为同样的形式
参数:可以接受一个参数来决定normalize的形式,有4个可选值
NFC(默认参数):标准等价合成,指视觉和语义上的等价
NFD:标准等价分解,在标准等价的前提下,返回合成字符分解出的多个简单字符
NFKC:兼容等价合成,返回合成字符。兼容等价 指语义上等价,直觉上不等价
NFKD:兼容等价分解:在兼容等价的前提下,返回合成字符分解出的多个简单字符
(一)除indexOf()外来确定一个字符串中是否包含灵感字符串的3中方法
includes():返回布尔值,表是否找到了参数字符串
参数:要查找的字符串
starsWith():返回布尔值,表参数字符串是否在源字符串的头部
参数:要查找的字符串
endsWith():返回布尔值,表参数字符串是否在源字符串的尾部
参数:要查找的字符串
其他一些方法
repeat():返回一个字符串,表示将原字符串重复n次
参数:次数n
注:
参数是小数,会被取整
参数是负数或者Infinity,会报错
参数在0-1之间,则等同于0
参数为NaN,则等同于0
padStar():头部补全 而 padEnd():尾部补全
参数1:指定字符串的最小长度
参数2:用于补全的字符串
注:
若原字符串的长度等于或大于指定的最小长度,返回原字符串
若用于补全的字符串与原字符串之和超出了指定的最小长度,则会截去超出位数的补全字符串
如果省略了第二个参数,会用空格补全
(二)模板字符串
``
可当做普通字符串使用
可定义多行字符串
可嵌套变量(需将变量写在${}中)
可调用函数
可嵌套模板字符串
String.raw():充当模板字符串的处理函数,返回一个反斜线都被转义的字符串,对应于替换变量后的模板字符串
也可当正常的函数使用,第一个从参数应该是一个具有raw属性的对象(应该是一个数组)
四、数值的扩展
ES6 中八进制要以前缀0o表示
(一)Number的扩展
Number.isFinite():检查一个数值是否为有限的
参数:要检查的数值
Number.isNaN():用于检查一个数值是否为NaN
参数:要检查的数值
Number.isInteger():判断一个数是否为整数
参数:要检查的数值
Number.isSafeInteger():判断一个数是否搂在这个范围之内,返回布尔值
参数:要检查的数值
(二)Math对象的扩展
Math.trunc():用于除去一个数的小数部分,返回整数部分
对于非数值,内部将其先转化为数值
对于空值和无法返回的值,返回NaN
参数:要检查的数值
Math.sign():判断一个数到底是正数,负数,还是0
参数有5中情况
参数为正数,返回+1
参数为负数,返回-1
参数为0,返回0
参数为-0,返回-0
其他值,返回NaN
注:对于非数值,会将其转换为数值
Math.cbrt():用于计算一个数的立方根(对于非数值,此案转换为数值)
Math.clz32():返回一个数的32位无符号整数形式有多少个前导0
参数:数值
对于小数,只考虑整数部分
对于空值和其他类型的值,先转换成为数值,在计算
Math.imul():返回两个数以32位带符号正数形式相乘的结果,返回的也是一个32位的带符号整数
Math.fround():返回一个数的单精度浮点数形式
Math.hypot():返回所有参数的平方和的平方根
若参数不是数值,会先转换成数值,在计算、
只要有一个参数无法转换为数值,就返回NaN
(1)对数
Math.expm1(x):返回e的x次方-1
Math.log1p(x):返回ln(1+x),如果x小于-1,返回NaN
Math.log10(x):返回以10 为底x的对数,如果小于0,返回NaN
Math.log2(x):返回以2 为底x的对数,如果小于0,返回NaN
(2)双曲函数
Math.sinh(x):返回x的双曲正弦
Math.cosh(x):返回x的双曲余弦
Math.tanh(x):返回x的双曲正切
Math.asinh(x):返回x的反双曲正弦
Math.acosh(x):返回x的反双曲余弦
Math.atanh(x):返回x的反双曲正切
(3)Math.signbit()
判断一个数的正负
参数是NaN,返回false
参数是-0,返回true
参数是负值,返回true
其他情况,返回false
(三)integer数据类型
必须要以后缀n来表示
二进制、八进制、十六进制都要以后缀n来表示
注:
几乎所有的Number运算都能用在integer中,除>>>和求证运算符+
Integer类型与Number类型不能混合运算,会报错
相等运算符(==)会改变数据类型,不能混合使用
精确相等运算符(===)不会改变数据类型,可以混合使用
五、函数的扩展
ES6允许为函数设置默认值,即直接写在参数定义的后面
使用参数默认值时,不能有同名的参数
注:参数默认值不是传值的,而是每次都重新计算默认值表达式的值(参数默认值是惰性求值)
通常情况下,定义了参数默认值的参数是函数的尾参数
有参数的默认值都是尾参数,除非显示输入undefined,如果传入的是undefined,将触发默认值,null不行
设置了默认值之后,或者默认值不是尾参数,函数的length不在计入后面的参数(length属性失真)
一旦设置了参数的默认值,函数在进行初始化的时候,参数会形成一个单独的作用域,等到初始化结束的时候,这个作用域消失(不设置参数默认值的时候不会出现)
利用参数默认值可以指定某一个参数不得省略,若省略则报错
可以将参数默认值设置为undefined,表示这个参可以省略
rest参数(形为“…变量名”),用于获取函数多余的参数
函数的name属性返回函数的函数名
箭头函数
ES6简明笔记中有
注:
箭头函数可以嵌套箭头函数
六、数组的扩展
扩展运算符 ( . . . )
主要用于函数调用
扩展运算符 后可以放表达式
如果扩展运算符后面是一个空数组,则不产生任何效果
可以合并数组
可以与结构赋值结合起来生成数组
若扩展运算符用于数组,只能放在参数的最后一位,否则报错
可以将字符串转为真正的数组
Array.from():将伪数组(两类对象:类似于数组的对象)转换为真正的数组
Array.of(一组值):将一组数转换为数组,若没有参数,则返回空数组
copyWithin():在当前数组内部将指定位置的成员复制到其他地方,然后返回数组(会修改数组)
接受3个参数
target(必选):从该位置开始替换数据
start(可选):从该位置开始读取数据,默认值为0,如果为负数,表示倒数
end(可选):到该位置停止读取数据,默认等于数组长度,若为负,表示倒数
fill():用于填充数组
参数1(必填):用于填充的给定值
参数2(可选):填充的起始位置
参数3(可选):填充的结束位置
entries()、keys()、value()用于遍历数组
entries():对键值对的遍历
keys():对键名的遍历
values():对键值的遍历
includes():表示某个数组是否包含给定的值,返回一个布尔值
参数1:给定值
参数2:搜索的起始位置,默认为0,若为负数,则表示倒数的位置,如果这时大于数组长度,则会重置为从0开始
数组的空位
数组的空位值数组的某一个位置没有任何值(空值不是undefined)
Array.from()会将数组的空位转换成为undefined
扩展运算符也会将空位转为undefined
copyWithin()会将空位一起复制
fill() 会将空位视为数组正常的位置
七、对象的扩展
ES6允许直接写入变量和函数作为对象的属性和方法
在对象中可只写属性名,不写属性值
可直接用标识符作为属性名,也可将表达式放在方括号内作为属性名(字面量定义)
Object.is():比较两个值是否严格相等,与严格相等运算符(===)的行为基本一致(注:有两个不同之处1:+0不等于 -0、2:NaN等于自身)
Object.assign():将源对象的所有可枚举属性复制到目标对象
第一个参数是目标对象,后面的参数是源对象
注:
只有一个参数,会返回改参数
若改参数不是对象,会先转换为对象,然后返回
由于undefined和null无法转换为对象,所以人工将它们作为参数就会报错
其他类似的值(数值、布尔)不在首参也不会报错,但是除了字符串会议数组的形式复制到目标对象,其他值都不会产生效果
Object.assign()是浅复制(即源对象的某个属性的值是对象,name目标对象复制得到的是这个对象的引用)
(一)对象的可枚举性
for…in循环:只遍历对象自身和继承的可枚举属性
Object.keys():返回对象自身的所有可枚举属性的键名
JSON.Stringify():只串化对象自身的可枚举属性
Object.assign():将源对象的所有可枚举属性复制到目标对象
注:所有class的原型的方法时不可枚举的
(二)属性的遍历
for…in:循环遍历对象自身和继承的可枚举属性(不包含Symbol属性)
Object.keys(obj):返回一个数组,包含对象自身的(不含继承的)所有可枚举属性(不包含symbol属性)
Object.getOwnPropertyNames(obj):返回一个数组,包含对象自身的所有属性(不含Symbol,但是含有不可枚举属性)
Object.getOwnPropertySymbols(obj):返回一个数组,包含对象自身的所有Symbol属性
Reflect.ownKeys(obj):返回一个数组,包含对象自身的所有属性,不管属性名是Symbol还是字符串,也不管是否可枚举
以上5中均遵循属性遍历次序规则
首先遍历所有属性名为数值的属性,按照数字排序
其次遍历所有属性名为字符串的属性,按照生成时间排序
最后遍历所有属性名为Symbol的属性,按照生成时间排序
(三)_ _ proto _ _属性
用于读取或者设置当前对象的prototype属性
缺点:兼容性和语义都不是很好
ES6使以下三种替换它
Object.setPrototypeOf(obj):用来设置一个对象的prototype属性,返回参数对象本身
参数:第一个参数若不是对象,则会自动转化为对象(undefined和null时会报错)
Object.getPrototypeOf():用于读取一个对象的prototype属性
参数:参数若不是对象,则会自动转化为对象(undefined和null时会报错)
Object.reate():生成对象
(四)对象的解构赋值和扩展运算符混用
对象的解构赋值会将所有的键值对都复制到新的对象上面
解构赋值必须是最后一个参数,否则会报错
解构赋值不会复制继承自原型对象的属性
扩展运算符可用于合并两个对象
若自定义的属性放在扩展运算符后面,则扩展运算符内部有同名属性会被覆盖
若把自定义属性放在扩展运算符前面,则变成了设置新对象的默认属性
若扩展运算符的参数是undefined或者null,则这两个值会被忽略,不会报错
若扩展运算符的参数对象之中有取值函数get,则这个函数会被执行
(四)Object.getOwnPropertyDescriptors(obj)
Object.getOwnPropertyDescriptor(obj):用于返回某个对象属性的描述对象
Object.getOwnPropertyDescriptors(obj):返回指定对象所有自身属性(非继承属性)的描述对象
主要是为了解决Object.assign()无法正确复制get属性和set属性
(五)Null传导运算符
四中用法
obj?.prop :读取对象属性
obj?.[expr]:读取对象属性
func.{…args}:函数或对象方法的调用
new C ?.{…args}:构造函数的调用
八、Symbol
新的数据类型,表示独一无二的值
通过symbol函数生成
let s=Symbol();
对象属性名的两种表示方法:1、原有字符串表示。2、Symbol表示
Symbol可接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台输出,或者是转为字符串时比较容易区分
如果Symbol的参数是一个对象,则会调用toString方法将其转换成为字符串,然后生成一个Symbol值
Symbol值不能与其他类型的值进行运算,否则会报错
Symbol值可以显式的转为字符串
let sym=Symbol('My Symbol');
String(sym); //'Symbol(My Symbol)'
sym.toString(); //'Symbol(My Symbol)'
Symbol值也可以转换成为布尔值,但是不能转换为数值
let sym=Symbol();
Boolean(sym); //true
!sym; //false
Number(sym); //TypeError
Symbol值作为对象的属性名时不能使用点运算符,只能用方括号
在对象内部使用Symbol值定义属性时,也只能用方括号
let sym=Symbol();
let a={};
a.sym='Hello';
a[sym]; //undefined
s['sym']; //'Hello'
Symbol类型的值还可以定义一组常量,保证这些常量都是不相等的
(一)属性名遍历
Object.getOwnPropertySymbols():返回一个数组,成员是当前对象的所有作用属性名的Symbol值
Reflect.ownKeys():以数组的形式返回所有键名,包括常规键名和S也Symbol键名
以Symbol值作为属性名的属性不会被常规方法遍历得到(可为对象定义一些非私有但又希望只用于内部的方法)
Symbol.for():可重新使用同一个Symbol值
参数:一个字符串
作用:搜索有没有以该参数作为名称的Symbol值,若有则返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值
Symbol.for()与Symbol都可以生成新的Symbol
区别:前者会被登记在全局环境中供搜索,后者不会
Singleton模式:调用一个类,并且在任何时候都返回同一个实例
(二)内置的Symbol值
对象的Symbol.hasInstance属性指向一个内部方法,对象使用instanceof运算符是会调用这个方法,判断该对象是否为某个构造函数的实例
class Myclass{
[Symbol.hanInstance](foo){
return foo instanceof Array;
}
}
[1,2,3] instanceof new Myclass; //true
对象的Symbo.isConcatSpreadable属性等于一个布尔值,表示该对象在使用Array.prototype.concat()时是否可以展开
let arr1=['c','d'];
['a','b'].concat(arr1,'e'); //['a','b','c','d','e']
arr1[Symvol.isConcatSpreadable] //undefined
let arr2=['c','d'];
arr2[Symbol.isConcatSpreadable]=false;
['a','b'].concat(arr2,'e'); //['a','b',['c','d'],'e']
数组的默认行为是可以展开的,Symbol.isConcatSpreadable属性等于undefined或者true,都可以
类似于数组的对象也可以展开,但它的Symbol.isConcatSpreadable属性默认为false,必须手动打开、
let obj={length:2,0:'c',1:'d'};
['a','b'].concat(obj,'e'); //['a','b',obj,'e']
obj[Symbol,isConcatSpreadable]=true;
['a','b'].concat(obj,'e'); //['a','b','c','d','e']
对于一个类而言,Symbol.isConcatSpreadable属性必须写成实例的属性
(1)Symbol.species
对象的Symbol.species属性指向当前对象的构造函数,使用这个函数返回的函数来创造新的实例对象
定义Symbol.species属性要用get读取数据
class Array extends Array{
//覆盖父类Array的构造函数
static get [Symbol.species](){return Array;}
(2)Symbol.match
对象的Symbol.match属性指向一个函数,当执行str.match(obj)时,如果该属性存在,则会调用它的返回值
(3)Symbol.replace
对象的Symbol.replace属性指向一个方法,当对象被String.prototype.replace方法调用时会返回改方法的返回值
(4)Symbol.split
对象的Symbol.split属性指向一个方法,当对象被String.prototype.split方法调用时会返回改方法的返回值
(5)Symbol.iterator
对象的Symbol.iterator属性指向该对象默认的遍历方法
(6)Symbol.toPrimitive
对象的Symbol.toPrimitive属性指向一个方法,对象在转化为原始数据类型时会调用这个方法,返回该对象的原始数据类型
参数:字符串,表示当前运算模式
Number:需要转化为数值
String:需要转化为字符串
Default:可转化为数组,也可转化为字符串
(7)Symbol.toStringTag
对象的Symbol.toStringTag属性指向一个方法,在对象上调用Object.prototype.toString()时,如果这个属性存在,其返回值会出现在toString方法返回值的字符串中,表示对象的类型
(8)Symbol.unscopables
对象的Symbol.unscopables属性指向一个对象,指定了使用with关键字时,那些属性会被with环境排除
九、Set和Map
(一)Set
类似于数组,其成员唯一,不重复
Set本身是一个构造函数,用于生产Set数据结构
let s=new Set();
Set函数可以接受一个数组,作为参数,用于初始化
向Set加入值时不会发生数据转换,即1和’1’为不同的值
在Set内部,两个NaN相等
(1)Set实例的属性
Set.prototype.Constructor():构造函数,就是Set()
Set.prototype.size():返回Set实例成员总数
add(value):添加值,返回Set本身
delete(value):删除值,返回一个布尔值,表删除是否成功
has(value):返回布尔值,表参数是否为Set成员
clear():清除所有成员,无返回值
(2)遍历
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach(function(){}):使用回调函数遍历每个成员,无返回值(可加参2,表示绑定的this对象)
Set的遍历顺序就是插入顺序
若想同步的改变原来的Set结构,可利用原Set映射出一个新的结构再复制给原Set结构,或者使用Array.from()
(二)WeaKSet
与Set类似,表不重复的集合
与Set的区别
WeakSet的成员只能是对象,不能是其他值
WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用
WeakSet的成员不能引用,因为其随时可能消失
WeakSet本生是一个构造函数,使用生成WeakSet数据结构
let w = new WeakSet();
可接受一个数组或者类似于数组的对象作为参数来初始化
WeakSet的方法
WeakSet.prototype.add(value ):添加新成员
WeakSet.prototype.delete(value):删除指定成员
WeakSet.prototype.has(value):返回布尔值,表指定值是否在WeakSet实例中
WeakSet无size属性,无法遍历其成员
(三)Map
类似于对象,也是键值组合
其键的范围不限于字符串,可为各种数据类型的值(包括对象)均可当做键
使用Map()构造函数生成
let m = new Map();
Map可接受一个数组作为参数,其数组成员为一个个表示键值对的数组
若一个键多次赋值,则后面的覆盖前面的值
若读取一个未知的键,则返回undefined
Map的键实际上绑定的是地址值,只要地址不同,即视为两个键(解决了同名属性碰撞的问题)
(1)Map实例的属性方法
1、size()
返回Map结构的成员总数
2、set(key,value)
设置key值所对应的键,然后返回Map结构
若key已经有值,则赋值更新,否则新生成该键值
3、get(key)
获取key对应的值,若找不到key则返回undefined
4、has(key)
返回一个布尔值,表示ley是否在Map结构中
5、delete(key)
删除某个键,删除成功则返回true,反之返回false
6、clear()
清除所有成员,无返回值
(2)遍历
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach(function(){}):遍历Map所有成员
Map的遍历顺序就是插入顺序
(四)Map与其他数据类型的转化
(1)Map转数组
Map转化为数组最快的方法时结合使用扩展运算符( . . . )
(2)数组转Map
将数组传入构造函数即可
(3)Map转对象
若Map所有键都是字符串,则可以转为对象
function strMapToObj(strMap){
let obj = Object.create(null);
for (let [k,v] of strMap){
obj[k]=v;
}
return obj;
}
(4)对象转Map
function objToStrMap(obj){
let strMap=new Map();
for(let k of Object.keys(obj)){
strMap.set(k.obj[k]);
}
return strMap;
}
(5)Map转JSON
情况一:Map键名都是字符串,可以转为对象JSON
function StrMapToJson(StrMap){
reutrn JSON.stringify(strMapToObj(strMap));
}
情况二:Map键名中含有非字符串,转为数组JSON
function mapToArrayJson(map){
return JSON.stringify(...map);
}
(6)JSON转Map
正常情况所有键名都是字符串
function jsonToStrMap(jsonStr){
return objToStrMap(JSON.parse(jsonStr));
}
特殊情况:在整个JSON就是一个数组,且数组成员本身又是由一两个成员的数组,此时应该一一对应的转为Map(数组转为JSON的逆操作)
function jsonToMap(jsonStr){
return new Map(JSON.parse(jsonStr));
}
(五)WeakMap
与Map结构类似,也用于生成键值对的集合
通过WeakMap函数生成
let wMap = new weakMap();
可使用set方法添加成员
可接受一个数组,作为构造函数的参数