老生常谈:constletvarclosure是函数作用域,摆脱全局作用域的影响。通过ES2015我们可以使用块级作用域来解决全局作用域的影响。for有两个级别的范围,每个级别都有自己的范围。for(leti=0;i<3;i++){//console.log(i);leti=99999console.log(i)}解析:leti=0;if(i<3){console.log(i)}i++const和letconst的区别只是声明了只读特性。必须分配const声明。const不允许修改它指向的内存地址。但是他的属性是可以修改的。最佳实践:在let中使用const而不是var。总结const和let结合可以让我们知道我们声明的变量是可读可写的。仍然是只读的。减少不可预测的结果。数组的解构当从结构中提取的成员小于要构造的数据时,将从左到右进行解构。当结构体提取的成员大于要结构化的数据时,extra会返回undefind。它类似于定义一个没有赋值的变量。constarr=[100,200,300];const[a,...res]=arr;console.log(a,res)//100[200,300]//赋默认值。const[a,,,d=2]=arr;根据key匹配值解构console.log(d)对象。constobj={name:'zce',age:18};constname='yoom';//如果结构体同名,可以创建别名。也可以加上默认值。const{名称:objName="123"}=obj;console.log(objName,name)模板字符串的高级用法constres=console.log`print`output:['print'];constname='tom';constgender='true'functionmyTagFunc(val,name,gender){console.log(val,name,gender)//输出:['hey,','isa','']'tom''true'//返回值等于res的值。returnval[0]+name+val[1]+gender+val[2]}constres=myTagFunc`嘿,${name}是一个${gender}`console.log(res)//嘿,tom是一个trueextensionmethod:constmessage=`Error:fooisnotdefind.`console.log(message.startsWith(''))//判断一个字符串的开头,返回一个布尔值trueconsole.log(message.endsWith('.'))//判断字符串某某结束返回布尔值falseconsole.log(message.includes('foo'))//字符串包含某某返回布尔值trueDefault值参数有默认值的参数需要放在参数的末尾。其余参数由es2015之前的js接收,其余参数使用arguments接收。之前:functionfoo(){console.log(arguments)//[Arguments]{'0':1,'1':2,'2':3,'3':4}}foo(1,2,3,4);es2015:functionfoo(first,...args){console.log(first,args)//1[2,3,4]}foo(1,2,3,4);了解箭头函数箭头函数表达式的语法比函数表达式更简洁。它没有自己的this、参数super或newtarget。箭头函数表达式更适合那些本来就需要匿名函数的人。它不能用作构造函数。高级语法://带括号的函数体返回对象的字面值params=>({foo:bar});//支持剩余参数和默认参数。参数支持解构。没有单独的这个。在箭头函数之前。每个新函数根据调用方式定义函数的this值。箭头函数不会创建自己的this,它只会从自己作用域链的上层继承this。this在当前范围内,没办法改变它的this.while阻塞了要执行的主进程不行,等我执行完再说。对象字面量的增强constbar='345';constobj={foo:123,//如果定义的变量与bar同名,可以这样简写,//如果函数名相同或者匿名,也可以简写。method1(){console.log(this,888)}//如果属性名是变量,可以写在方括号中。[Math.random()]:123;}console.log(obj);obj.method1()Object.assign扩展方法Object.assign是深拷贝?????constsource1={a:123,b:123}constsource2={a:789,d:789}consttarget={a:456,c:456}//Object.assign()合并右边的对象向左,如果两个对象具有相同的键,则右侧将替换左侧的值。如果右边有东西,左边没有,就加上这个属性。constresult=Object.assign(target,source1,source2)console.log(target===result,target)//truefunctionfunc(obj){//用于复制一个新对象。letnewObj=Object.assign({},obj)//在函数内部操作。不改变外面的价值。newObj.name='功能对象';console.log(newObj,2)}constobj={name:'globalobj'};func(obj);console.log(obj);Object.is判断两个值是否相等(不是很有用)console.log(//+0===-0//NaN===NaN//判断NaN等于NaNObject.is(NaN,NaN),//判断+0不等于-0Object.is(-0,+0))Object.defineProperty和ProxyObject.defineProperty不能监听对象的删除操作。代理可以。constperson={name:'zce',age:20};//第一个参数没有目标代理功能。第二个参数是一个对象,它也监听deletedeleteProperty方法。并返回一个新对象。constpersonProxy=newProxy(person,{//一个是代理对象,一个是需要删除的属性,删除后,原来的对象属性也会被删除。deleteProperty(target,property){console.log('delete',property);删除目标[属性];}})删除personProxy.age;console.log(personProxy,person,personProxy===person)//{name:'zce'}{name:'zce'}falseProxy专门用作对象的访问代理。可以监视对象的读取和写入。constperson={name:'zce',age:20};//Proxy第一个参数是要代理的对象。第二个参数是一个对象。ThisobjecthasagetsetdeletePropertymethodconstpersonProxy=newProxy(person,{//get方法有两个参数,一个是代理对象,一个是传递的属性。//这个属性可能存在也可能不存在。get(target,property){//判断是否有该属性并返回,如果没有则返回默认值returnpropertyintarget?target[property]:'我没有你要的';},//set方法,一共有三个参数.target被代理的对象property:传入的属性,这个属性可以存在也可以不存在,如果没有,就是新添加的属性,如果有,就是更新oldproperty.你可以根据需要进行逻辑判断。set(target,property,value){if(property==='age'&&!Number.isInteger(value)){thrownewTypeError(`${value}isnotanint`)}目标[属性]=值}})personProxy.age=true;console.log(personProxy.name);console.log(personProxy.a);console.log(personProxy);数组中的方法将在VUE中重写。替换数组原型上的方法。从而达到监控的目的。而Proxy可以很好的监听数组的变化。proxymonitorarrayconstlist=[];//第一个参数是一个数组。通过set监控bush的数据。constlistProxy=newProxy(list,{set(target,property,value){console.log('set',property,value,0);target[property]=value;returntrue;}})listProxy.push(100)listProxy.push(10)set01000//两边输出不知道为什么。设置长度10设置1100设置长度20
