当前位置: 首页 > Web前端 > vue.js

临时死区和函数作用域

时间:2023-03-31 22:31:09 vue.js

临时死区临时死区是从变量声明到声明完成的阻塞。在声明完成之前,这个块是一个封闭的范围。如果在声明变量之前使用变量,则变量不可用,称为临时死区。var没有临时死区,因为var有变量提升let,const有块级作用域,没有变量提升,有临时死区console.log(a);//报错Cannotaccess'a'beforeinitializationleta='东方不败'console.log(b);//报错Cannotaccess'b'beforeinitializationconstb='东方不败'console.log(c);//undefined因为var存在变量提升varc='东方球白'ES6规定如果代码块中有let和const命令声明的变量,这个块从一开始就为这些变量形成一个封闭的作用域,这些变量不能直到声明语句完成才可以访问(get或set),否则会报ReferenceError。这在语法上叫做“时间死区”(英文temporaldeadzone,简称TDZ),也就是从代码块开始到变量生命语句完成的区域。函数作用域案例1一旦设置了参数的默认值,当函数初始化时,参数将形成一个单独的作用域。初始化完成后,这个作用域就会消失。此语法不设置参数的默认值。不会出现。varx=1functionf(x,y=x){console.log(y);}f(2)//2在上面的例子中,这里的函数参数(x,y=x),这个区域是一个单独的函数域,y的默认x变量指向第一个参数x,不是全局变量x,这里调用f函数,将值2传给x,y=xtheny=2,打印结果为2case2letx2=1functionf2(y2=x2){letx2=2console.log(y2);}f2()//1调用f2函数,由于f2函数没有给参数,y2=x2形成一个单独的作用域,在这个函数域中,x2没有定义,所以x2指向外层全局变量x2,y2=x2,即y2=1,这里,函数内部的x2不起任何作用。执行函数时,先执行参数,再执行函数体。//报错functionf2(y2=x2){letx2=2console.log(y2);}f2()//报错上面的例子中,如果去掉了全局变量x2,就会报错,因为这个变量没有声明,给y2赋值了一个未声明的变量,就报错了。varxx=1functionfxx(xx=xx){console.log(xx);}fxx()上面的写法也会报错,因为函数的参数有一个单独的作用域,在这个参数的作用域内,执行结果是让xx=xx,将一个未声明的变量xx赋值给xx并报错一个错误。(临时死区)如果函数的默认参数是一个函数,那么函数的作用域也必须遵循这个规则。letfoo='out'functionbar(func=()=>foo){letfoo='come'console.log(func());}bar()//本例中函数参数默认为func,值为匿名函数,返回值为变量foo。由于这里的函数参数形成了一个单独的作用域,变量foo并没有在这个作用域中定义,所以foo会指向外层的全局变量foo。如果去掉全局变量foo='out',会报错,赋值一个未声明的变量。应用程序可以利用这个特性写一个参数默认值来抛出错误,如果参数没有传递就抛出错误。functionthrowErr(){thrownewError('参数不能省略')}functionomits(mustfn=throwErr()){returnmustfn}omits();//Throwerrorwithoutparameters:parametersmustnotbeomitted不传参调用省略函数,函数默认会调用throwErr()函数并抛出错误。如果该参数的默认值设置为undefined,则表示该参数可以省略。其余参数argumentsarguments可以获取函数的参数值和函数信息(名称,长度)等。functionau(arr){console.log('arguments:',arguments);}au(2,1,4,3)可以通过数组方法对函数参数进行操作,比如排序。arguments对象不是数组,而是类数组对象。为了使用数组方法,您必须先使用Array.from将其转换为数组。functionau(arr){//通过数组方法对函数参数进行排序returnArray.from(arguments).sort();}console.log(au(2,1,4,3))//[1,2,3,4]rest参数ES6提供了rest参数,语法:(...变量名),其实就是rest运算符,通过rest参数,可以方便的对函数参数进行操作,rest参数是一个真正的数组。//resy参数(残差运算符)functionresidue(...val){console.log(val);//[1,2,3]}residue(1,2,3)rest参数(残差运算符)只能放在最后一个地方,否则会报错//functionresidue2(...val,b){}//剩余运算符不是最后一个地方,会报错functionresidue3(c,...val){console.log(c,val);//1[2,3,4,5]}residue3(1,2,3,4,5)以上参数完成的参数排序,使用rest可以轻松完成,语义更强,更容易读。让au2=(...val)=>val.sort()console.log(au2(2,1,4,3));//[1,2,3,4]strictmodeES5启动,函数内部可以设置为严格模式:functions(){'usestrict'//strictmode}//es5strictmodefunctions(){'usestrict'//strictmode//code.......}ES6do做了修改,规定只要函数参数使用默认值、解构赋值、展开运算符,内部就不能显示strict模式函数,否则会报错。//es6严格模式报错,因为函数的默认值是setfunctions2(a,b=a){'usestrict'//Code.....}//报错,使用解构赋值consts3=function({a,b}){'usestrict'}//错误,使用剩余的运算符consts4=(...a)=>{'usestrict'}es6这样设置的原因是函数内部的严格模式应该同样适用于函数体和函数参数。但是函数执行时,会先执行参数,再执行函数体。这样,就会出现一些不精确的情况。只有函数体才能知道参数是否应该在严格模式下执行,但函数的参数确实先执行,所以es6修改了严格模式下函数参数的行为。functions5(val=070){'usestrict'returnval}s5()//这部分报错中,函数默认值为八进制070,strict中不能使用前缀0表示八进制模式,所以报错。但实际上,由于函数设置了默认参数,函数先执行参数,然后进入函数体。由于es6限制,报错。有两种方法可以规避此限制。第一种:设置全局严格模式'usestrict'functions6(val=100){console.log(val);}s6()//100第二种方法:把函数嵌套在一个无参立即函数consts7=()=>{'使用严格'让一个;return(function(val=200){returnval})()}console.log(s7());匿名函数调用方式:在上面的例子中(function(val=200){returnval})(),wrap整个return函数用(),在最后加一个()调用,函数中的()表示调用。案例源码:https://gitee.com/wang_fan_w/es6-science-institute如果您觉得本文对您有帮助,请点亮star