let
1.let 声明的变量在let 命令所在的代码快内有效
2.不声明直接用变量或者先用再声明都会报错
3.暂时性死区:在变量声明之前就使用变量的代码块1
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
4.不允许在同一级别块域内重复声明一个变量
5.let 声明的变量,外层代码块不受内层代码块的影响
—-外层作用域无法读取内层作用域的变量
—-内层作用域可以定义外层作用域的同名变量
6.块级作用域内声明的函数,行为类似于var声明的变量,仅在所在的代码块内有效
const
1.声明的同时进行复制
2.作用域特征同let
3.当声明的变量为对象或者数组时,只可以改变对象属性或数组元素的值,但不可以将变量重新赋值
ES6 6种声明变量的方法:var、function、let、const、import、class
var命令和function命令声明的全局变量,依旧是顶层对象的属性;let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
解构赋值
数组
1.‘模式匹配’,左右对应相等,变量取值由位置决定
2.当右边的数据量大于左边变量数,如果是单层数组,则依次匹配,多余形成数组赋给最后一个变量
—-如果变量组成多层数组,则依次匹配,剩余的舍弃
3.当右边小于左边变量数,多余的变量的值就等于undefined
4.可以提前给变量赋默认值,默认值可以是已声明的其他变量,
–注意给变量赋‘undefined’的值的时候,如果变量原来的值不严格等于‘===’undefined,将不会被赋值为undefined
对象
1.对象的属性没有次序,变量必须与属性同名,才能取到正确的值,属性是匹配的标志
2.若变量与属性名不一致,则先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者(变量),而不是前者(属性)
3.如果在声明对象变量的时候为属性值的变量赋值,则相当于同时声明属性值的变量
4.进行套嵌赋值时,注意分清属性名和变量名,被赋值的是变量名,不是属性名
5.进行默认值赋值规则同数组,赋空不会生效
6.属性名表达式1
2
3
4let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
数组arr的0键对应的值是1,[arr.length - 1]就是2键,对应的值是3
函数参数
类似数组,但注意下面两种写法1
2
3
4
5
6
7
8function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
为变量x和y赋值1
2
3
4
5
6
7
8function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
为x,y的默认值赋值
字符串、数字、布尔
字符串:字符串被转换成数组
数字/布尔:先转换成对象
字符串方法
方法 | es5/js | es6 | 2017 |
---|---|---|---|
Unicode表示法 | 只限于\u0000——\uFFFF之间的字符 | 只要将码点放入大括号,就能正确解读该字符 | |
charCodeAt | 只会正确返回16位的UTF-16字符的码点 | ||
codePointAt | 会正确返回32位的UTF-16字符的码点 | ||
String.fromCharCode | 只会识别16位的UTF-16字符 | ||
String.fromCodePoint | 会会识别32位的UTF-16字符 | ||
for | 不可以识别大于0xFFFF的码点 | ||
for…of | 可以识别大于0xFFFF的码点 | ||
charAt | 不能识别码点大于0xFFFF的字符 | ||
at | 能识别码点大于0xFFFF的字符 | ||
normalize | ‘\u01D1’===’\u004F\u030C’ //false | ‘\u01D1’.normalize() === ‘\u004F\u030C’.normalize()// true | |
indexOf | 确定一个字符串是否包含在另一个字符串中 | ||
includes() | 返回布尔值,表示是否找到了参数字符串 | ||
startsWith | 返回布尔值,表示参数字符串是否在源字符串的头部 | ||
endsWith | 返回布尔值,表示参数字符串是否在源字符串的尾部 | ||
repeat(n) | 返回一个新字符串,表示将原字符串重复n次。 | ||
padStart(),padEnd() | padStart()用于头部补全,padEnd()用于尾部补全 | ||
模板字符串 | 反引号(`),保留空格和换行,变量名写在${}中 |
数值处理方法
方法 | es5/js | es6 | 2017 |
---|---|---|---|
二进制和八进制表示法 | 在严格模式之中,八进制就不再允许使用前缀0表示 | 二进制0b或0B、八进制0o或0O | |
isFinite()/isNaN() | 先调用Number()将非数值的值转为数值,再进行判断 | ||
Number.isFinite() | 检查一个数值是否为有限的,非数值一律返回false。 | ||
Number.isNaN() | 检查一个值是否为NaN,非数值一律返回false。 | ||
parseInt()、parseFloat() | 移植到Number对象上面,行为完全保持不变。 | ||
Number.isInteger() | 判断一个值是否为整数 | ||
Number.EPSILON | 极小的常量,为浮点数计算设置一个误差范围 | ||
Number.isSafeInteger | 判断一个整数是否落在整数范围之内 | ||
Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER | 表示整数范围的上下限 | ||
Math.trunc | 去除一个数的小数部分,返回整数部分 | ||
Math.sign | 判断一个数到底是正数、负数、还是零 | ||
Math.cbrt | 计算一个数的立方根 | ||
Math.clz32 | 返回一个数的32位无符号整数形式有多少个前导0 | ||
Math.imul | 返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。 | ||
Math.fround | 返回一个数的单精度浮点数形式 | ||
Math.hypot | 返回所有参数的平方和的平方根 | ||
Math.expm1(x) | 返回Math.exp(x) - 1 | ||
Math.log1p(x) | 返回1 + x的自然对数 | ||
Math.log10(x) | 返回以10为底的x的对数 | ||
Math.log2(x) | 返回以2为底的x的对数 | ||
Math.sign() | 判断一个值的正负 | ||
指数运算符(**) | 指数运算符与Math.pow的实现不相同 | ||
Math.sinh(x) | 返回x的双曲正弦 | ||
Math.cosh(x) | 返回x的双曲余弦 | ||
Math.tanh(x) | 返回x的双曲正切 | ||
Math.asinh(x) | 返回x的反双曲正弦 | ||
Math.acosh(x) | 返回x的反双曲余弦 | ||
Math.atanh(x) | 返回x的反双曲正切 |
深入理解es6笔记
let/const
常量如果是对象,则对象中的值可以修改
js引擎在扫描代码发现变量声明时,要么将它们提升至作用域顶部(var),要么将声明放到TDZ(let/const),访问TDZ中的变量会触发运行时错误,只有执行过变量声明语句后,变量才会从TDZ中移出,然后可正常访问。
TDZ在块作用域中,相对于let,const所在块作用域来说。
但在let声明的作用域外对该变量使用typeof不会报错1
2
3
4console.log(typeof val);
if(condition) {
let value = 'blue'
}
字符串、正则表达式
在对字符串进行比较排序操作前,按照统一标准进行标准化1
2
3let normalized = values.map(function(text){
return text.normalize();// 默认NFC格式
})
正则表达式Y修饰符使用注意:
1.只有调用exec()和test()这些正则表达式对象的方法时才会涉及lastIndex属性,调用字符串方法,例如match(),则不会触发粘滞行为
2.对于粘滞正则表达式而言,如果使用^字符串来匹配字符串开端,只会从字符串的起始位置或多行模式的首行进行匹配。
函数
函数name属性不一定引用同名变量,他只是协助调试用的额外信息,所以不能使用name属性的值来获取对函数的引用
js函数有两个不同的内部[[Call]]和[[Construct]]
当通过new关键字调用函数时,执行的是[[Construct]]函数,他负责创建一个被称作实例的新对象
然后在执行函数将this绑定到实例上;
如果不通过new关键字调用函数,则执行[[Call]]函数,从而直接执行代码中的函数体
具有[[Construct]]方法的函数被统称为构造函数。
可以在函数内部使用new.target来判断是否在使用new 操作符调用函数,
以及判断是否被某个特定构造函数调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
221.
function Person(name){
if(typeof new.target !== 'undefined'){
this.name = name;
}else {
throw new Error('必须通过new 操作符调用该函数')
}
}
2.
function Person(name){
if(typeof new.target !== 'Person'){
this.name = name;
}else {
throw new Error('必须通过new 操作符调用该函数')
}
}
function AnotherPerson(name){
Person.call(this,name)
}
var person = new Person('kely');
var anotherPerson = new AnotherPerson('kely'); // 抛出错误
如果箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this;
否则this会被设置为全局对象
对象
在使用===进行比较时,+0和-0得到结果相等;NaN和自身比较不相等
但可以使用Object.is()方法弥补
Object.js(+0,-0)得到false;
Object.js(NaN,NaN)得到true.
Object.assign()方法不能将提供者的访问器属性复制到接收对象中
会被转变成接收对象中的一个数据属性。
对象自有属性枚举顺序的基本规则是
1.所有数字键按升序排序
2.所有字符串键按照他们被加入对象的顺序排序
3.所有Symbol键按照他们被加入对象的顺序排序
Super引用相当于指向对象原型的指针,实际上也就是Object.getPrototypeof(this)的值
解构
获取数组副本1
2
3let colors = ['red','green'];
let [...cloneColor] = colors;
通过给解构参数提供默认值,将解构参数定义为可选的
1 | function setCookie(name, value ,{secure,path,domain}={}){} |
为解构参数指定默认值
1 | const setCookieDefaults = { |
Symbol
使用Symbol.for()可以创建可共享的Symbol
使用Symbol.keyFor()可以在Symbol全局注册表中检索共享的Symbol
使用Symbol创建的Symbol属性不能用Symbol.keyFor()去查找
Symbol类型的值不可以被转化为数字或者字符串
Object.getOwnPropertySymbol()可以返回包含所有Symbol自有属性的数组
一些特殊的Symbol值被用于暴露更多语言内部逻辑
主要使用思路就是通过这些特殊Symbol属性覆盖掉原始方法的响应方式
例如
给一个对象A定义
|属性|覆盖方法|被调用时机|
|—|—|—|
|Symbol.hasInstance|instanceOf|C instanceOf A|
|Symbol.toPrimitive|默认数字字符串转换值|A+’!’|
|Symbol.toStringTag|Object.prototype.toString(),Object.prototype.toString.call()方法时的返回值|A.toString或者Object.prototype.toString.call(A)|
1 | 1. |
用于覆盖正则表达式的方法1
2
3
4
5
6
7
8
9
10
11
12let hasLengthOf10 = {
[Symbol.match]: function(value){return ...},
[Symbol.replace]: function(value,replacement){return 。。。},
[Symbol.search]: function(value){return ...},
[Symbol.split]: function(value){return ...},
}
let str = 'hwrwrirrrk';
console.log(str.match(hasLengthOf10))
console.log(str.replace(hasLengthOf10))
console.log(str.search(hasLengthOf10))
console.log(str.split(hasLengthOf10))
Set 和 Map
Set中如果存储对象的话,是强引用,只要Set实例中引用存在,垃圾回收机制就不能释放该对象的内存空间。
WeakSet 只存储对象弱引用,并且不可以存储原始值,如果集合中的弱引用是对象的唯一引用,则会被回收并释放相应内存
所以如果只需要跟踪对象引用,应该使用WeakSet集合而不是普通的Set集合。
WeakMap集合中的键名必须是一个对象,如果使用非对象键名会报错:
集合中保存的是这些对象的弱引用,如果在弱引用之外不存在其他的强引用,
引擎的垃圾回收机制会自动回收这个对象,同时也会移除WeakMap集合中的键值对
但是只有集合的键名遵从这个规则,键名对应的值如果是一个对象,则保存的是对象的强引用,不会触发垃圾回收机制
数组方法
find和findIndex方法都接受两个参数,一个是回调函数,
另一个是可选参数,用于指定回调函数中this的值
fill 方法可以传入第二个和第三个参数用于只改变一部分值,分别指定开始索引和不包含结束索引
Proxy 和 Reflect
使用Proxy的陷阱方法,可以拦截对象的默认特性方法
对应的Reflect方法可以在proxy陷阱方法中重新使用对象的内减特性
1 | let target = { |
模块
用逗号将默认的本地名称与大括号包裹的非默认值分隔开,请记住,在import语句中,默认值必须排在非默认值之前。