block-levelscope(执行结果题)block-levelscope阮一峰block-levelscopevara=1999;{console.log(a);//函数a(){}a=2020;函数a(){}a=2021;}console.log(a);//我对2020的理解:(原理可能有误,但是很容易理解,错误的是函数不能声明在块级,浏览器会有自己的支持行为,类似于函数表达式声明——参考阮一峰。声明不要使用函数声明的方式,而是函数表达式的方式。)在块级,编译过程,函数声明变量提升,执行过程不受影响。所以functiona(){}在块级之外,在编译过程中,有一个outside,没有作用。当执行该过程时,搜索开始。由于a的查找顺序是从词法环境({})到变量环境(var),查找的最接近,所以是2020(注意这里是执行阶段,函数a(){}变量提升是编译阶段)ps。与变量相比,函数将被优先考虑。(我的理解:这意味着函数将取代变量提升)事件冒泡,事件捕获,事件代理(事件委托)事件冒泡:轻微事件捕获:轻微事件代理:使用事件冒泡在target.addEventListener(type,听众,使用捕获);在父元素中,useCapture为false时为事件冒泡,默认为false。Object常用方法:Object.defineProperty定义的描述:{value,writable,configurable,emunable},或{set,get,configurable,emunable}Object.create,Object.keys,Object.values,Object.entries,Object.toStringObject.preventExtensions组织扩展对象作用域、作用域链和上下文作用域是指函数定义时声明变量的空间。作用域链是指在变量查找过程中,从当前上下文开始逐层查找到父级,最后查找到全局。当一个函数被声明时,会有一个作用域属性,它包含了所有的父变量。此时,VO对象,包括内部函数、变量、形式参数,都存储在上下文中。函数执行时,AO对象,包括函数内部、变量、形参、内部this,挂载在作用域链上。作用域、作用域链、执行上下文栈介绍了解原型链待补充Promise和asynchronous常见的异步请求:Nativevarrequest=newHttpXMLRequest()request.open('GET',url);request.responseType='json'request.onload=function(){}request.send()实现要添加的Promise//Promise//Promise.prototype.then//Promise.prototype.all//Promise.prototype.resolve//Promise.prototype.raceeventloopandeventqueue事件循环:事件队列(单位是消息,消息关联一个回调函数,从消息队列中弹出后,回调函数会被调用到形成一个执行框架)执行栈(单位是框架,包括函数中的变量和参数)堆(保存对象结构)同步任务和异步任务window.requestAnimationFrame()既不是宏任务也不是Microtasks,而是执行闭包下次浏览器重绘时。两个主要特点:函数防止外部函数引用内部变量。函数可以使用外部变量在闭包中引用this。因为闭包是在内存中执行的,所以this通常指向全局,可以通过调用来改变。闭包的作用是通过立即执行函数来模拟块级作用域,减少变量的声明到全局作用域。另外,由于立即执行函数执行后没有外部引用,所以内存会立即释放。使用var声明时,使用立即执行函数遍历时,可以准确获取面向对象编程(不是通过new构造)functionPerson(){varname='default';return{getName:function(){返回名称;},setName:function(newName){名称=newName;}}};varp1=Person();console.log(p1.getName());//defaultp1.setName('wang');console.log(p1.getName());//wangclose包的问题是在闭包中引用dom会造成循环引用,不能GC(引用计数)//在IE9之前,dom连销毁都做不到functionclosure(){varelement=文档.getElementById(ID);element.onclick=function(){console.log(element.id);}//Destroyelement//element=null}this指向闭包,返回局部作用域变量,内存不会立即释放es8中要补充的类中的supersuper可以作为函数使用,也可以作为对象使用。为函数时,相当于父类的构造函数,只能在子类的构造函数中使用。this指向子类的实例。A类{构造函数(){this.show();}show(){console.log('一个实例');}}B类扩展A{constructor(){super();}显示(){控制台。log('B实例');}}newB()//当B实例为对象时,在一般函数中使用时,super相当于父类原型对象,this指向子类实例。A类{构造函数(){this.x='A';}say(){console.log(this.x)}}classBextendsA{constructor(){super();this.x='B'}}letb=newB();console.log(b.say())//Bps。注意提醒classA{constructor(){//构造函数上定义的属性和方法等同于父类实例上定义的属性和方法,不是原型对象this.p=2;}}classBextendsA{getm(){returnsuper.p;}}letb=newB();console.log(b.m)//undefined//扩展题函数A(x){this.p=x}A.prototype.p=2//此时p有已通过构造函数声明newA().p//undefinedsuper指向静态方法中this父类常用代码防抖和throttling防抖是指经过一段时间积累后触发,比如监听在输入框中输入文本时为onChange。functiondebounce(fn,delay){让定时器返回function(){constself=this;常量参数=参数;如果(计时器){clearTimeout(计时器);}timer=setTimeout(function(){fn.apply(self,args);},delay)}}letlog=debounce(function(){console.log('!')},5000)window.addEventListener('resize',log)throttling是指多少Repeatedtrigger只执行一次,比如重复点击。functionthrottle(fn,delay){让计时器返回function(){constself=this;常量参数=参数;如果(计时器){返回;}timer=setTimeout(function(){self.apply(fn,args)timer=null;},delay)}}letlog=throttle(function(){console.log('!')},3000)window.addEventListener('click',log)造成这种差异的原因:throttlewhen第一次执行arg时是固定的,也就是说如果使用throttle是放在输入框的onChange场景中,该值将是第一个输入数字。防抖,通过不断的clearTimeout更新要执行的函数,直到没有触发,等待延时再执行。delay的作用是如果在此期间再次触发,会重新写入clearTimeout。new//Object.create会更新__proto__,即[[Prototype]],维护原型链functioncreate(proto){if(typeofproto!=='object'&&typeofproto!=='function'){thrownewTypeError("Prototypescanonlybeobjects")}if(proto===null){thrownewTypeError("Cannotbenull")}//functionF(){}//F.prototype=proto;//返回新的F();proto.constructor.prototype=protoreturnnewproto.constructor()}functionnewOperator(ctor){if(typeofctor!=='function'){throw'构造函数必须是一个方法'}newOperator.target=ctor;//es6可以直接使用Object.create//constinstance=Object.create(ctor.prototype)constinstance=create(ctor.prototype)constargs=[].slice.call(arguments,1)//bindthisand执行构造函数constr=ctor.apply(instance,args);//如果构造函数返回,则返回构造函数if(r){returnr;}//实例returninstance;}functionPerson(name){this.name=name}constw=newOperator(Person,"zs")console.log(w)handwrittenbindfunctionbind(fn,obj){constargs=[].slice.调用(参数,1);常量自我=这个;returnfunctionbound(){returnfn.call(obj,[].slice.call(arguments,1).concat(args))}}consth={name:'zs',}functionsay(){控制台。log(this.name)}constbound=bind(say,h)bound()Object.isPolyfillif(!Object.is){Object.defineProperty(Object,"is",{value:function(x,y){if(x===y){//1.如果x===y,且都不为0//2.如果x,y都为0,判断符号是否相等returnx!==0||1/x===1/y;}else{//将NaN与自身进行比较包含:Number.NaN,0/0,NaNreturnx!=x&&y!=y;}}})}如何实现Array.reduce()加入curry和compose加入Object.assign()加入实现字符Stringrepeat//nativerepeat'ni'.repeat(3);//'ninini'//实现一个String.prototype.repeatString1=function(n){returnArray(n+1).join(this);}控制台.log('ni'.repeatString1(3));//实现两个String.prototype.repeatString2=function(n){returnArray(n).fill(this).join('');}console.log('ni'.repeatString2(3));js模板引擎Function('让a=1');其他
