我不爱吃洋芋 發表於 2021-3-11 23:35:00

Javascript深入理解ES6

<p><span style="font-size: 16px">参考文献:《深入理解ES6》</span></p>
<p><span style="font-size: 18pt"><strong>目录</strong></span></p>
<p><span style="font-size: 18px">第一章:块级作用域和let、const<br></span></p>
<p><span style="font-size: 18px">第二章:字符串</span></p>
<p><span style="font-size: 18px">第三章:函数</span></p>
<p><span style="font-size: 18px">第四章:对象的扩展</span></p>
<p><span style="font-size: 18px">第五章:解构赋值对象/数组</span></p>
<p><span style="font-size: 18px">第六章:Symbol和Symbol属性</span></p>
<p><span style="font-size: 18px">第七章:Set集合和Map集合</span></p>
<p><span style="font-size: 18px">第八章:迭代器(iterator)和生成器(generator)</span></p>
<p><span style="font-size: 18px">第九章:类(class)</span></p>
<p><span style="font-size: 18px">第十章:改进的数组功能</span></p>
<p><span style="font-size: 18px">第十一章:Promise</span></p>
<p><span style="font-size: 18px">第十二章:代理(proxy)和反射(reflection)</span></p>
<p><span style="font-size: 18px">第十三章:用模块封装代码</span></p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt"><strong>第一章 块级作用域和let、const</strong></span></p>
<p><strong><span style="font-size: 16px">1、什么是变量提升?</span></strong></p>
<p><span style="font-size: 16px">es5中,我们使用var来声明变量,但是var会存在 “<strong>变量提升”。</strong></span></p>
<p><span style="font-size: 16px">什么是变量提升?就是变量会被提升至<strong>当前作用域</strong>的最顶端</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210205105823751-1135497131.png">&nbsp; &nbsp;<img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210205110017438-480240228.png"></span></p>
<p><span style="font-size: 16px">如上图所示,变量value被提升,但是赋值操作被留在了原地,所以其他地方的value值为undefined。</span></p>
<p><span style="font-size: 16px">es6引入块级作用域来强化对变量声明周期的控制</span></p>
<p><strong><span style="font-size: 16px">2、什么是块级声明?</span></strong></p>
<p><span style="font-size: 16px">大白话就是在指定作用域内声明变量,其他作用域无法访问。</span></p>
<p><span style="font-size: 16px">书中说的作用域有两种,函数内部,块中(即 { 和 } 中),但是其实有些许不准确。</span></p>
<p><span style="font-size: 16px">{...} 并没有形成作用域,而是因为es6中 let、const的特性,让 {...}形成了作用域,如果是在{...}中使用var声明,那么它就不具备作用域的效果。</span></p>
<p><strong><span style="font-size: 16px">3、let 声明</span></strong></p>
<p><span style="font-size: 16px">先了解下它做重要的2个特性</span></p>
<p><span style="font-size: 16px">(1)不存在变量提升</span></p>
<p><span style="font-size: 16px">(2)同一个作用域中不能重复定义已经存在的变量</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210205112335097-461040019.png"></p>
<p><strong><span style="font-size: 16px">&nbsp;4、const 声明</span></strong></p>
<p><span style="font-size: 16px">先了解它最重要的几个特性</span></p>
<p><span style="font-size: 16px">(1)不存在变量提升</span></p>
<p><span style="font-size: 16px">(2)一旦声明必须赋值初始化,一旦赋值不可修改</span></p>
<p><span style="font-size: 16px">(3)同一个作用域中不能重复定义已经存在的变量</span></p>
<p><span style="color: rgba(51, 51, 153, 1)"><span style="font-size: 16px"><strong>值得注意的是,const声明变量赋值为基本类型后,再次修改会报错。但是如果赋值引用类型数据,可以修改其值,原因是引用类型数据存储的只是</strong></span><span style="font-size: 16px"><strong>指向真正数据的地址而已,我们修改数据并不会影响这个地址的变化。</strong></span></span></p>
<p><strong><span style="font-size: 16px">5、临时死区(Temporal Dead Zone 简称TDZ)</span></strong></p>
<p><span style="font-size: 16px">通常用来描述let、 const的不提升效果。Javascript 引擎在扫描代码时遇到var声明的变量,就将它提升到顶部。遇到 let 或者 const 声明,就将它放到TDZ中。</span></p>
<p><span style="font-size: 16px">访问TDZ中的变量就会报错,只有当执行过变量声明的语句,才会从TDZ中移除,然后正常访问。</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210205114059600-904559300.png"></p>
<p><span style="font-size: 16px">这种情况注意一下:</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210205114740398-644035461.png"></p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt">&nbsp;<strong>第二章 字符串</strong></span></p>
<p><strong><span style="font-size: 16px">1、es6新增字符串方法</span></strong></p>
<p><span style="font-size: 16px">(1)includes() 方法,检测字符串中是否包含指定字符</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218205913624-1898404900.png"></p>
<p><span style="font-size: 16px">&nbsp;(2)startsWith() 方法,检测字符串是否以指定字符开头</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218210045836-2089010227.png"></p>
<p><span style="font-size: 16px">&nbsp;(3)endsWith() 方法,检测字符串是否以指定字符结尾</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218210154457-723809344.png"></p>
<p><span style="font-size: 16px">&nbsp;以上三个检测字符串的方法都支持第二个参数,表示从下表n的位置开始检索。如果直接传入正则表达式而不是字符串,会报错</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218210504824-735792661.png"></p>
<p><span style="font-size: 16px">&nbsp;(4)repeat() 方法,将一个字符串复制n遍</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218210813984-1113051158.png"></p>
<p><strong><span style="font-size: 16px">2、<strong>模板字面量</strong></span></strong></p>
<p><span style="font-size: 16px">es6新增模板字面量创建字符串,使用方式只是将原本的单/双引号替换成符号&nbsp; ` hello `</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218185956883-1305284168.png"></span></p>
<p>&nbsp;<span style="font-size: 16px">模板字面量的三种用途</span></p>
<p><span style="font-size: 16px">(1)可以创建多行字符串</span></p>
<p><span style="font-size: 16px">在es6之前,如果使用单、双引号,字符串一定要在同一行才行,不能直接换行。想要换行字符串,按照以下方法:</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218190831549-1389152020.png"></p>
<p><span style="font-size: 16px">&nbsp;ES6简化了换行字符串的步骤,直接打换行即可</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218191249719-2028639385.png"></p>
<p><span style="font-size: 16px">用et message = `like\nyou` 来换行也可以,&nbsp; \n 表示换行&nbsp;</span></p>
<p>&nbsp;<span style="font-size: 16px">(2)字符串占位符</span></p>
<p><span style="font-size: 16px">可以在字符串中嵌套可访问作用域中的变量、运算、函数调用等</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218195933089-263783782.png"></p>
<p>&nbsp;<span style="font-size: 16px">(3)模板标签</span></p>
<p><span style="font-size: 16px">每个模板标签都可以执行模板字符串上的转换并返回最终的字符串值</span></p>
<p><span style="font-size: 16px">标签指:第一个反撇号(`)前的字符串,如下示例的模板标签是makeStr</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218202048166-2117074084.png"></p>
<p>&nbsp;<img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218202710127-1253916120.png"></p>
<p><strong><span style="font-size: 18pt">第三章 函数</span></strong></p>
<p><span style="font-size: 16px"><strong>1、命名参数的默认值</strong></span></p>
<p><span style="font-size: 16px">(1)如何设置默认值</span></p>
<p><span style="font-size: 16px">在ES6之前,给函数参数指定默认值的方式如下:</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218214104421-1080759349.png"></span></p>
<p>&nbsp;ES6简化了为形参提供默认值的过程,没有传入值则为其提供一个默认值</p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218214656201-639069286.png"></p>
<p><span style="font-size: 16px">&nbsp;(2)默认参数对arguments的影响</span></p>
<p><span style="font-size: 16px">ES6之前的非严格模式下,形参值的变化会更新到arguments中。(严格模式下,arguments的值还是最开始那个值)</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218215206803-1785368318.png"></span></p>
<p><span style="font-size: 16px">&nbsp;在ES6中,无论是否定义严格模式,arguments都与严格模式下的行为一致</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218215716147-1496509206.png"></p>
<p><span style="font-size: 16px">&nbsp;(3)可以使用先定义的参数作为后定义参数的默认值,相反先定义不能使用后定义的参数</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218220756197-1647125715.png"></span></p>
<p><span style="font-size: 16px"><strong>&nbsp;2、无命名参数</strong></span></p>
<p><span style="font-size: 16px">无论函数已定义的命名函数有多少,都不限制调用时传入的实际参数数量,调用时总是可以传入任意数量的参数</span></p>
<p><span style="font-size: 16px">(1)如何设置不定参数</span></p>
<p><span style="font-size: 16px">在函数的命名参数前加三个点(...),表示这是一个不定参数,该参数为一个数组,包含着自它之后传入的所有参数。通过这个数组名可以逐一访问里面的参数。</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218221509163-1301394530.png"></span></p>
<p>&nbsp;<span style="font-size: 16px">注意:每个函数只能声明一个不定参数,且一定要放在所有参数的最后一个位置,否则会报错</span></p>
<p><span style="font-size: 16px">(2)不定参数对arguments对象的影响</span></p>
<p><span style="font-size: 16px">无论是否使用不定参数,arguments总是包含所有传入函数的参数</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218222131730-1516451470.png"></span></p>
<p><strong><span style="font-size: 16px">&nbsp;3、展开运算符</span></strong></p>
<p><span style="font-size: 16px">展开运算符可以让你指定一个数组,将它们打散后作为各自独立的参数传入函数</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218223258997-885810018.png"></span></p>
<p><strong><span style="font-size: 16px">&nbsp;4、ES6为所有函数新增了name属性</span></strong></p>
<p><span style="font-size: 16px">函数name的值不一定引用同名变量,只作为开发调试的额外信息,所以不要使用name的值来获取对于函数的引用</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218225241383-1919758645.png"></span></p>
<p><strong><span style="font-size: 16px">&nbsp;5、判断函数是否作为构造函数使用(通过new 关键字)</span></strong></p>
<p><span style="font-size: 16px">ES5中,对于函数来说,无法知道是通过Person.call() 或者Person.apply() 还是new关键字调用得到的Person实例</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210218235802224-1420845650.png"></span></p>
<p>&nbsp;<span style="font-size: 16px">ES6中引入new.target元属性(指非对象的属性),当new时,new.target被赋值为new操作符的目标。修改this指向则为undefined。</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210219000538970-1251603185.png"></span></p>
<p><span style="font-size: 16px"><strong>&nbsp;6、箭头函数</strong></span></p>
<p><span style="font-size: 16px">(1)语法</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210219001932243-1660911581.png"></span></p>
<p>&nbsp;<span style="font-size: 16px">(2)箭头函数和普通函数的区别</span></p>
<ul>
<li><span style="font-size: 16px">没有this绑定,不能使用new创建实例</span></li>
<li><span style="font-size: 16px">调用call、apply、bind方法不会报错,但没有任何效果</span></li>
<li><span style="font-size: 16px">虽然没有this绑定,但是它的this取决于该函数外部非箭头函数的this</span></li>
<li><span style="font-size: 16px">箭头函数没有arguments属性,但是它可以访问外围函数的arguments</span></li>
<li><span style="font-size: 16px">箭头函数没有原型</span></li>


















</ul>
<p><strong><span style="font-size: 16px">7、尾调用优化</span></strong></p>
<p><span style="font-size: 16px">(1)什么是尾调用</span></p>
<p><span style="font-size: 16px">尾调用指的是函数作为另一个函数的最后一条语句被调用。如果是递归,将带来一定消耗。</span></p>
<p><span style="font-size: 16px"><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210219003420312-1133784507.png"></span></p>
<p>&nbsp;<span style="font-size: 16px">(2)ES6中,满足条件下,尾调用不会再创建新栈帧表示函数被调用,而是清除并且重用当前栈帧。</span></p>
<ul>
<li><span style="font-size: 16px">尾调用不访问当前栈帧的变量(函数不是一个闭包)</span></li>
<li><span style="font-size: 16px">在函数内部,尾调用是最后一条语句</span></li>
<li><span style="font-size: 16px">尾调用的结果作为函数值返回</span></li>


















</ul>
<p><span style="font-size: 16px">无法优化的几种情况</span></p>
<p><img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210219004410859-215013927.png"></p>
<p><span style="font-size: 16px">&nbsp;(3)尾调用的优化是引擎帮助我们做的事情,我们要做的就是让我们写的代码可以被引擎优化。递归是尾调用优化最显著的场景,我们码代码时也要要想想尾调用优化的特性。</span></p>
<p>&nbsp;<img src="https://img2020.cnblogs.com/blog/2112309/202102/2112309-20210219010233009-1631977558.png"></p>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18pt">第四章 对象的扩展</span></strong></p>
<p><span style="font-size: 16px"><strong>1、ES6中对象属性和方法的简写</strong></span></p>
<p><span style="font-size: 16px">(1)当对象的属性名与变量名相同时,可以只写属性名</span></p>
<p><span style="font-size: 16px">(2)可以直接在对象中定义可变属性名</span></p>
<p><span style="font-size: 16px">(3)对象中可以直接写方法,而不用再写function</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> es6中</span>
let myName = '良人非良'<span style="color: rgba(0, 0, 0, 1)">
let hello </span>= '小黄鸭'<span style="color: rgba(0, 0, 0, 1)">
let obj </span>=<span style="color: rgba(0, 0, 0, 1)"> {
myName,
: </span>'world'<span style="color: rgba(0, 0, 0, 1)">,
sayHi () {
    console.log(</span><span style="color: rgba(0, 0, 255, 1)">this</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> world</span>
<span style="color: rgba(0, 0, 0, 1)">},
}

obj.sayHi()
console.log(obj) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> world</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> es6之前</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> myName = '良人非良'
<span style="color: rgba(0, 0, 255, 1)">var</span> hello = '小黄鸭'
<span style="color: rgba(0, 0, 255, 1)">var</span> obj =<span style="color: rgba(0, 0, 0, 1)"> {
myName: myName, </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 必须属性名和属性都写</span>
sayHi: <span style="color: rgba(0, 0, 255, 1)">function</span> () { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 必须写属性名,并且定义完整函数</span>
    console.log(<span style="color: rgba(0, 0, 255, 1)">this</span>) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> world</span>
<span style="color: rgba(0, 0, 0, 1)">},
}
obj </span>= 'world' <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 给对象添加一个可计算的属性(属性为变量)</span>
console.log(obj) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> world</span>
obj.sayHi()</span></pre>
</div>
<p><strong><span style="font-size: 16px">2、ES6中对象中新加的方法</span></strong></p>
<p><span style="font-size: 16px">(1)Object.is()&nbsp; 弥补全等运算的不准确 比如+0和-0是不同的实例,但是+0 === -0 的值为true</span></p>
<p><span style="font-size: 16px">选择那种写法根据自己的代码来</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">console.log(+0 === -0) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(Object.is(+0, -0)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
<span style="color: rgba(0, 0, 0, 1)">
console.log(</span>5 === '5') <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(Object.is(5, '5')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
<span style="color: rgba(0, 0, 0, 1)">
console.log(NaN </span>=== NaN) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(Object.is(NaN, NaN)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span></span></pre>
</div>
<p><span style="font-size: 16px">(2)Object.assign()&nbsp; 合并多个对象的属性,重复属性根据 ’后面覆盖前面‘ 原则,最终返回一个对象,同时第一个对象会跟着改变</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let obj1 =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'我是老大'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">,
}
let obj2 </span>=<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'我是老二'<span style="color: rgba(0, 0, 0, 1)">,
hobby: </span>'eat'<span style="color: rgba(0, 0, 0, 1)">,
}
let obj3 </span>=<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'我是老三'<span style="color: rgba(0, 0, 0, 1)">,
sex: </span>'男'<span style="color: rgba(0, 0, 0, 1)">,
}
let resObj </span>=<span style="color: rgba(0, 0, 0, 1)"> Object.assign(obj1, obj2, obj3)
console.log(resObj) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> { name: '我是老三', age: 18, hobby: 'eat', sex: '男' }</span>
console.log(obj1) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> { name: '我是老三', age: 18, hobby: 'eat', sex: '男' }</span></span></pre>
</div>
<p><strong><span style="font-size: 16px">3、ES6中对象的自由属性被枚举时的返回顺序按照以下规则来排序</span></strong></p>
<p><span style="font-size: 16px">(1)属性名为数字键时按升序排序(优先于字符串)</span></p>
<p><span style="font-size: 16px">(2)属性名为字符串时按照加入对象时的顺序排序(优先于Symbol键)</span></p>
<p><span style="font-size: 16px">(3)所有symbol键按照它们被加入对象的顺序排序</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let obj =<span style="color: rgba(0, 0, 0, 1)"> {
b: </span>1<span style="color: rgba(0, 0, 0, 1)">,
</span>9: 1<span style="color: rgba(0, 0, 0, 1)">,
</span>0: 1<span style="color: rgba(0, 0, 0, 1)">,
</span>3: 1<span style="color: rgba(0, 0, 0, 1)">,
a: </span>1<span style="color: rgba(0, 0, 0, 1)">,
}
obj.d </span>= 1<span style="color: rgba(0, 0, 0, 1)">

console.log(Object.getOwnPropertyNames(obj))
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [ '0', '3', '9', 'b', 'a', 'd' ]</span></span></pre>
</div>
<p><span style="font-size: 16px"><strong>4、ES6中增强了对象原型</strong></span></p>
<p><span style="font-size: 16px">(1)添加了Object.setPrototypeOf(p1,p2)方法,在对象被创建后修改它的原型。接收两个参数</span></p>
<p><span style="font-size: 16px">需要改变原型的对象p1</span></p>
<p><span style="font-size: 16px">代替p1原型的p2</span></p>
<p><span style="font-size: 16px; color: rgba(255, 0, 0, 1)">注意:只有函数有prototype属性,这里说的对象原型,是隐式原型__proto__</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let person =<span style="color: rgba(0, 0, 0, 1)"> {
sayHi () {
    console.log(</span>'我是人'<span style="color: rgba(0, 0, 0, 1)">)
}
}

let cat </span>=<span style="color: rgba(0, 0, 0, 1)"> {
sayHi () {
    console.log(</span>'我是小猫猫'<span style="color: rgba(0, 0, 0, 1)">)
}
}

let boy </span>=<span style="color: rgba(0, 0, 0, 1)"> Object.create(person)
boy.sayHi() </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我是人</span>
console.log(Object.getPrototypeOf(boy) === person) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
<span style="color: rgba(0, 0, 0, 1)">
Object.setPrototypeOf(boy, cat)
boy.sayHi() </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我是小猫猫</span>
console.log(Object.getPrototypeOf(boy) === cat) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> Object.getPrototypeOf(obj)为es5中返回指定对象原型的方法</span>
<span style="color: rgba(0, 0, 0, 1)">
console.log(boy.__proto__ </span>=== Object.getPrototypeOf(boy)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span></span></pre>
</div>
<p><span style="font-size: 16px">(2)引入了关键字 super,指向当前对象的原型</span></p>
<p><span style="font-size: 16px">注意:super始终固定,不会因为多重继承而改变</span></p>
<p><span style="font-size: 16px">super只能在简写方法的对象中使用(对象中可以直接写方法,而不用再写function),否则报错</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let person =<span style="color: rgba(0, 0, 0, 1)"> {
sayHi () {
    console.log(</span>'我是人'<span style="color: rgba(0, 0, 0, 1)">)
}
}

let boy </span>=<span style="color: rgba(0, 0, 0, 1)"> {
sayHi () {
    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true   super =&gt; Object.getPrototypeOf(this)</span>
    console.log(super.sayHi === Object.getPrototypeOf(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">).sayHi)
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> Object.getPrototypeOf(<span style="color: rgba(0, 0, 255, 1)">this</span>).sayHi.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">)
}
}
Object.setPrototypeOf(boy, person)
boy.sayHi() </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我是人</span></span></pre>
</div>
<p><span style="font-size: 16px"><strong>5、给了函数和方法一个正式的定义</strong></span></p>
<p><span style="font-size: 16px">(1)定义在对象中的是方法</span></p>
<p><span style="font-size: 16px">(2)通过function定义的是函数&nbsp;</span></p>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18pt">第五章:解构赋值对象/数组</span></strong></p>
<p><span style="font-size: 16px"><strong>1、ES6中的对象解构</strong></span></p>
<p><span style="font-size: 16px">(1)对象的解构</span></p>
<p><span style="font-size: 16px">&nbsp;语法糖,简化了操作,将要的属性从对象中提取出来。</span></p>
<p><span style="font-size: 16px">注意:let { name, age } = obj 中的name,age要和obj中的属性名一致才可以提取成功,否则为undefined</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ES6中获取对象中的属性</span>
let obj =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'良人非良'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">,
hobby: </span>'eat'<span style="color: rgba(0, 0, 0, 1)">
}

let { name, age, hobb } </span>=<span style="color: rgba(0, 0, 0, 1)"> obj
console.log(name) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(age) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 18</span>
console.log(hobb) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> undefined</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ES6之前</span>
let obj =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'良人非良'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">
}
let name </span>=<span style="color: rgba(0, 0, 0, 1)"> obj.name
let age </span>=<span style="color: rgba(0, 0, 0, 1)"> obj.age
console.log(name) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(age) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 18<br></span></span></pre>
</div>
<p><span style="font-size: 16px">(2)解构中的默认值</span></p>
<p><span style="font-size: 16px">可以为解构的值赋默认值,当为undefined时取默认值</span></p>
<p><span style="font-size: 16px; color: rgba(255, 0, 0, 1)">注意:值为null时,取的是null值</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let obj =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'良人非良'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">,
hobby: </span>'eat'<span style="color: rgba(0, 0, 0, 1)">,
}
let { name, a </span>= 1 } =<span style="color: rgba(0, 0, 0, 1)"> obj
console.log(name) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(a) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1 obj中并没有属性a,结构出来是undefined,但是我们设置了默认值1</span></span></pre>
</div>
<p><span style="font-size: 16px">(3)为非同名局部变量赋值</span></p>
<p><span style="font-size: 16px">可以理解为给我们解构出来的属性改个名字</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let obj =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'良人非良'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">,
hobby: </span>'eat'<span style="color: rgba(0, 0, 0, 1)">,
a: </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">,
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 原本的属性名是name</span>
let { name } =<span style="color: rgba(0, 0, 0, 1)"> obj
console.log(name) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 改了新名字,叫newName</span>
let { name: newName } =<span style="color: rgba(0, 0, 0, 1)"> obj
console.log(newName) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(name) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 再去获取name,直接报错name is not defined</span></span></pre>
</div>
<p><span style="font-size: 16px">(4)嵌套对象的解构</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let obj =<span style="color: rgba(0, 0, 0, 1)"> {
name: </span>'良人非良'<span style="color: rgba(0, 0, 0, 1)">,
age: </span>18<span style="color: rgba(0, 0, 0, 1)">,
hobby: </span>'eat'<span style="color: rgba(0, 0, 0, 1)">,
boyfriend: {
    name: </span>'大肥猪'<span style="color: rgba(0, 0, 0, 1)">,
    age: </span>8<span style="color: rgba(0, 0, 0, 1)">,
}
}
let { boyfriend: { name, age } } </span>=<span style="color: rgba(0, 0, 0, 1)"> obj
console.log(name) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 大肥猪</span>
console.log(age) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 8</span></span></pre>
</div>
<p><span style="font-size: 16px"><strong>2、数组的解构</strong></span></p>
<p><span style="font-size: 16px">(1)解构</span></p>
<p><span style="font-size: 16px">注意:数组的解构与变量名字无关,只与变量的下标相关</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 解构出第一个第二个的值赋值给自定义的变量</span>
let arr =
let </span>=<span style="color: rgba(0, 0, 0, 1)"> arr
console.log(first) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span>
console.log(second) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果只想要指定位置的数据,可以将前面的数据留空</span>
let [, , , four] =<span style="color: rgba(0, 0, 0, 1)"> arr
console.log(four) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 不定元素的解构:将数组剩余的部分解构赋值给numArr</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> PS: ...numArr 必须在数组的最后,否则报错</span>
let =<span style="color: rgba(0, 0, 0, 1)"> arr
console.log(num1) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span>
console.log(numArr) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 234</span></span></pre>
</div>
<p><span style="font-size: 16px">&nbsp;(2)赋值&nbsp;</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 替换值</span>
let arr =
let first </span>= 'hello'<span style="color: rgba(0, 0, 0, 1)">
let second </span>= 'world'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上一行代码记得加上分号,否则会将[]解析成上一行中的内容</span>
=<span style="color: rgba(0, 0, 0, 1)"> arr
console.log(first) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span>
console.log(second) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 交换值</span>
let a = 1<span style="color: rgba(0, 0, 0, 1)">
let b </span>= 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 上一行代码记得加上分号,否则会将[]解析成上一行中的内容</span>
[ a, b ] =<span style="color: rgba(0, 0, 0, 1)"> [ b, a ]
console.log(a) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 2</span>
console.log(b) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span></span></pre>
</div>
<p><span style="font-size: 16px">(3)解构中的默认值</span></p>
<p><span style="font-size: 16px">注意:值为null时,取的是null值</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let arr =
let =<span style="color: rgba(0, 0, 0, 1)"> arr
console.log(first) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 1</span>
console.log(second) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> hello</span>
console.log(four) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 3</span></span></pre>
</div>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18pt">第六章:Symbol和Symbol属性</span></strong></p>
<p><strong><span style="font-size: 16px">1、在es6之前的简单类型(原始类型)和为什么使用Symbol?</span></strong></p>
<p><span style="font-size: 16px">(1)原始类型:String、Number、Boolean、Null、undefined。</span></p>
<p><strong><span style="font-size: 16px">2、创建Symbol</span></strong></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let symName =<span style="color: rgba(0, 0, 0, 1)"> Symbol()
let obj </span>=<span style="color: rgba(0, 0, 0, 1)"> {}
obj </span>= '良人非良'<span style="color: rgba(0, 0, 0, 1)">
console.log(symName) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Symbol()</span>
console.log(obj) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(symName <span style="color: rgba(0, 0, 255, 1)">in</span> obj) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(<span style="color: rgba(0, 0, 255, 1)">typeof</span> symName) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> symbol 使用typeOf判断symbol类型</span></span></pre>
</div>
<p>&nbsp;<span style="font-size: 16px">Symbol()接收一个可选参数,通常用来为这个symbol添加文本描述,便于阅读开发</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let symName = Symbol('我是symbol类型,我表示名字'<span style="color: rgba(0, 0, 0, 1)">)
console.log(symName) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Symbol('我是symbol类型,我表示名字')</span></span></pre>
</div>
<p><strong><span style="font-size: 16px">3、Symbol的使用方法</span></strong></p>
<p><span style="font-size: 16px">(1)symbol注册表,使用Symbol.for()方法定义的symbol,会被存在注册表中,当下一次创建symbol,会去表中查找是否注册过相同的symbol,有则取出,无则创建并在表中注册</span></p>
<p><span style="font-size: 16px">symbol.for()接收一个参数,标识创建这个symbol的标识字符串(简单理解成就是这个symbol的id值,每次根据这个id值来查找)</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let uid = Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('uid'<span style="color: rgba(0, 0, 0, 1)">)
let uid2 </span>= Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('uid'<span style="color: rgba(0, 0, 0, 1)">)
console.log(uid </span>=== uid2) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
<span style="color: rgba(0, 0, 0, 1)">
let obj </span>=<span style="color: rgba(0, 0, 0, 1)"> {}
obj </span>= '良人非良'<span style="color: rgba(0, 0, 0, 1)">
console.log(obj) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(obj) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span></span></pre>
</div>
<p><span style="font-size: 16px">Symbol.keyFor():在注册表中检索和symbol相关的键(就是上面注册时用的身份证id)</span></p>
<div class="cnblogs_code">
<pre>let uid = Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('uid'<span style="color: rgba(0, 0, 0, 1)">)
console.log(Symbol.keyFor(uid)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> uid</span>
<span style="color: rgba(0, 0, 0, 1)">
let uid2 </span>= Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('uid'<span style="color: rgba(0, 0, 0, 1)">)
console.log(Symbol.keyFor(uid2)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> uid</span>
<span style="color: rgba(0, 0, 0, 1)">
let uid3 </span>= Symbol('uid'<span style="color: rgba(0, 0, 0, 1)">)
console.log(Symbol.keyFor(uid3)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> undefined</span></pre>
</div>
<p><span style="font-size: 16px">(2)Symbol不支持强制转换成String和Number,直接使用运算符报错</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let sm = Symbol.<span style="color: rgba(0, 0, 255, 1)">for</span>('1'<span style="color: rgba(0, 0, 0, 1)">)
console.log(sm </span>+ 'world') <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cannot convert a Symbol value to a string</span>
console.log(sm / 1) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Cannot convert a Symbol value to a number</span></span></pre>
</div>
<p><span style="font-size: 16px">(3)检索Symbol属性</span></p>
<p><span style="font-size: 16px">在ES5中,Object.kes() 返回一个包含所有可枚举属性的数组</span></p>
<p><span style="font-size: 16px">Object.getOwnPropertyNames() 返回一个包含所有可枚举或不可枚举属性的数组</span></p>
<p><span style="font-size: 16px">它们无法识别并检索出Symbol值</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let sym = Symbol()<br>let obj =<span style="color: rgba(0, 0, 0, 1)"> {
a: </span>1<span style="color: rgba(0, 0, 0, 1)">,
b: </span>2<span style="color: rgba(0, 0, 0, 1)">,<br> : 3
}
console.log(Object.keys(obj.__proto__)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> []</span>
<span style="color: rgba(0, 0, 0, 1)">console.log(Object.getOwnPropertyNames(obj.__proto__))
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'constructor',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   '__defineGetter__',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   '__defineSetter__',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'hasOwnProperty',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   '__lookupGetter__',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   '__lookupSetter__',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'isPrototypeOf',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'propertyIsEnumerable',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'toString',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'valueOf',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   '__proto__',</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">   'toLocaleString'</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> ]</span></span></pre>
</div>
<p><span style="font-size: 16px">ES6提供Object.getOwnPropertySymbols()方法用于获取symbol属性的数组,注意:只返回symbol类型</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let sym =<span style="color: rgba(0, 0, 0, 1)"> Symbol()
let obj </span>=<span style="color: rgba(0, 0, 0, 1)"> {
a: </span>1<span style="color: rgba(0, 0, 0, 1)">,
b: </span>2<span style="color: rgba(0, 0, 0, 1)">,
: </span>3<span style="color: rgba(0, 0, 0, 1)">,
}
console.log(Object.getOwnPropertySymbols(obj)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [ Symbol() ]</span></span></pre>
</div>
<p><span style="font-size: 16px"><strong>&nbsp;4、通过well-known Symbol暴露内部操作</strong></span></p>
<p>&nbsp;</p>
<p><strong><span style="font-size: 18pt">第七章:Set集合和Map集合</span></strong></p>
<p><span style="font-size: 16px"><strong>1、Set集合</strong></span></p>
<p><span style="font-size: 16px">(1)Set集合是一种无重复的有序列表,无法通过索引访问集合中的元素</span></p>
<p><span style="font-size: 16px">(2)常用操作</span></p>
<ul>
<li><span style="font-size: 16px">set.add() 新增一个元素</span></li>
<li><span style="font-size: 16px">set.has() 判断集合中是否存在某个元素</span></li>
<li><span style="font-size: 16px">set.delete() 移除集合某个元素</span></li>
<li><span style="font-size: 16px">set.size 判断集合长度</span></li>
<li><span style="font-size: 16px">set.clear() 移除所有元素</span></li>
</ul>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let set = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Set()
let o1 </span>=<span style="color: rgba(0, 0, 0, 1)"> {}
let o2 </span>=<span style="color: rgba(0, 0, 0, 1)"> {}
set.add(</span>5<span style="color: rgba(0, 0, 0, 1)">)
set.add(</span>'5'<span style="color: rgba(0, 0, 0, 1)">)
set.add(o1)
set.add(o2)
console.log(set) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Set { 5, '5', {}, {} }</span>
console.log(set.size) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 4</span>
console.log(set.has('5')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(set.has(o1)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(set.has({})) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(set.has('xxx')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(set.<span style="color: rgba(0, 0, 255, 1)">delete</span>(5)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span></span></pre>
</div>
<p>&nbsp;<span style="font-size: 16px">注意:在对象中,属性只能是字符串,所以不管属性是函数、数字,最后都会被解析成对应的字符串</span></p>
<ul>
<li><span style="font-size: 16px">遍历Set:forEach()方法  </span></li>
</ul>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">set.forEach((val, index, set) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
console.log(val, index, set)
})
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 因为set没有索引,所以第一个值和第二个值相同</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 11 11 Set { 11, 22, 33 }</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 22 22 Set { 11, 22, 33 }</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 33 33 Set { 11, 22, 33 }</span></span></pre>
</div>
<ul>
<li><span style="font-size: 16px">将Set转为数组</span></li>
</ul>
<p><span style="font-size: 16px">因为set没有索引,所以需要将set转为数组才可以通过下标访问</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let set = <span style="color: rgba(0, 0, 255, 1)">new</span> Set()
let arr </span>=<span style="color: rgba(0, 0, 0, 1)"> [...set]
console.log(arr) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> [ 1, 2, 3 ]</span></span></pre>
</div>
<p>(3)Weak Set</p>
<p>Set类型被看作是强引用的类型,将对象存储在Set的实例中和存储在变量中一样,只要Set实例的引用存在,垃圾回收器就不能释放该对象的内存空间。所以ES6中引入Weak Set 只存储对象的弱引用。</p>
<ul>
<li><span style="font-size: 16px">Weak Set 只能存储对象,不可以存储原始值</span></li>
<li><span style="font-size: 16px">集合中的弱引用如果是对象唯一的引用,会被回收释放内存</span></li>
<li><span style="font-size: 16px">Weak Set 不支持迭代,所以for...of、foreach等迭代器不支持</span></li>
<li><span style="font-size: 16px">不支持size属性</span></li>
<li><span style="font-size: 16px">不支持clear方法</span></li>
<li><span style="font-size: 16px">has() delete()方法传入一个非对象,返回false</span></li>
</ul>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let wset = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> WeakSet()
let obj </span>=<span style="color: rgba(0, 0, 0, 1)"> {}
wset.add(obj)

console.log(wset.has(obj)) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(wset.has('hello')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(wset.<span style="color: rgba(0, 0, 255, 1)">delete</span>('hello')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
obj = <span style="color: rgba(0, 0, 255, 1)">null</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 移除对象obj的强引用,weak Set中的引用也自动移除</span>
console.log(wset) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span></span></pre>
</div>
<p><span style="font-size: 16px"><strong>2、Map集合</strong></span></p>
<p><span style="font-size: 16px">(1)存储键值对的有序列表,键和值支持所有类型的数据</span></p>
<p><span style="font-size: 16px">(2)常用的方法</span></p>
<ul>
<li><span style="font-size: 16px">map.set()&nbsp; 往map中添加数据&nbsp;</span></li>
<li><span style="font-size: 16px">map.get()&nbsp; 获取数据</span></li>
<li><span style="font-size: 16px">map.has()&nbsp; 判断指定键名在map中是否存在</span></li>
<li><span style="font-size: 16px">map.delete() 移除指定键名和对应的值</span></li>
<li><span style="font-size: 16px">map.clear() 移除所有的键和值</span></li>
<li><span style="font-size: 16px">map.size() 获取map元素的个数</span></li>
</ul>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let map = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Map()
map.set(</span>'name', '良人非良'<span style="color: rgba(0, 0, 0, 1)">)
map.set(</span>'age', 18<span style="color: rgba(0, 0, 0, 1)">)
map.set(</span>'hobby', 'eating'<span style="color: rgba(0, 0, 0, 1)">)
console.log(map.get(</span>'name')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 良人非良</span>
console.log(map.get(1)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> undefined</span>
console.log(map.has('hobby')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
console.log(map.has(2)) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> false</span>
console.log(map.<span style="color: rgba(0, 0, 255, 1)">delete</span>('age')) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> true</span>
<span style="color: rgba(0, 0, 0, 1)">map.clear()
console.log(map.size) </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 0</span></span></pre>
</div>
<p><span style="font-size: 16px">简写:可以向map传入一组数组初始化集合</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 16px">let map = <span style="color: rgba(0, 0, 255, 1)">new</span> Map([['name', '良人非良'], ['age', 18<span style="color: rgba(0, 0, 0, 1)">]])

</span></span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 等同于<br></span></pre>
<pre><span style="font-size: 16px">let map = new Map()
map.set('name', '良人非良')
map.set('age', 18)</span></pre>
</div>
<p><span style="font-size: 16px">(3)Weak Map</span></p>
<ul>
<li><span style="font-size: 16px">无需列表&nbsp;</span></li>
<li><span style="font-size: 16px">键名必须是对象,值可以为任意类型</span></li>
<li><span style="font-size: 16px">如果弱引用之外不存在其他强引用,垃圾回收器会自动回收这个引用</span></li>
<li><span style="font-size: 16px">不支持clear方法,不支持size属性</span></li>
</ul>
<p><strong><span style="font-size: 18pt">第八章:迭代器(iterator)和生成器(generator)</span></strong></p>
<p><strong><span style="font-size: 18pt">第九章:类(class)</span></strong></p>
<p><strong><span style="font-size: 18pt">第十章:改进的数组功能</span></strong></p>
<p><strong><span style="font-size: 18pt">第十一章:Promise</span></strong></p>
<p><strong><span style="font-size: 18pt">第十二章:代理(proxy)和反射(reflection)</span></strong></p>
<p><strong><span style="font-size: 18pt">第十三章:用模块封装代码</span></strong></p>
<p>持续更新ing...</p>

</div>
<div id="MySignature" role="contentinfo">
    只想摸鱼且菜到抠脚的基层酸菜鱼。。。<br><br>
来源:https://www.cnblogs.com/liandudu/p/14376975.html
頁: [1]
查看完整版本: Javascript深入理解ES6