暂时性死区
暂时性死区也就是变量申明到申明实现的区块,这个区块是一个关闭的作用域,直到申明实现。
如果在变量申明之前应用该变量,那么该变量是不可用的,也就被称为暂时性死区。
var
没有暂时性死区,因为var
存在变量晋升let、const
有块级作用域,没有变量晋升,存在暂时性死区
console.log(a); // 报错 Cannot access 'a' before initializationlet a = '东方不败'
console.log(b); // 报错 Cannot access 'b' before initializationconst b = '东方不败'
console.log(c); // undefined 因为var存在变量晋升var c = '西方求败'
ES6
规定,如果代码块中存在let
和const
命令申明的变量,这个区块对这些变量从一开始就造成了关闭作用域,直到申明语句实现,这些变量能力被拜访(获取或设置),否则会报错ReferenceError
。这在语法上称为“暂时性死区”(英temporal dead zone,简 TDZ),既代码块开始到变量生命语句实现之前的区域。
函数作用域
案例一
一旦设置了参数的默认值,函数进行生命初始化时,参数就会造成一个独自的作用域,等初始化完结,这个作用域就会隐没,这种语法在不设置参数默认值时不会呈现。
var x = 1function f(x,y = x){ console.log(y); }f(2) // 2
下面这个例子中,函数参数这里(x,y = x)
,这个区域就是独自的作用域,y
默认的x
变量指向第一个参数x
,而不是全局变量x
,这里调用f函数,向x
传递数值2
,y = x
那么 y = 2
,打印后果为2
案例二
let x2 = 1function f2(y2 = x2){ let x2 = 2 console.log(y2); }f2() // 1
调用f2
函数,因为未给f2
函数任何参数,并且 y2 = x2
造成一个独自的作用域,在这个作用域里x2
并未定义,所以x2
指向的是外层全局变量x2
,y2 = x2
也就是y2 = 1
,在这里,函数外部的x2
并未起到任何作用。
函数执行的时候会先执行参数,再执行函数体。
// 报错function f2(y2 = x2){ let x2 = 2 console.log(y2); }f2() // 报错
下面的例子中,如果去掉全局变量x2
则会报错,因为变量为申明,给y2
赋值了一个未声明的变量,报错。
var xx = 1function fxx(xx = xx){ console.log(xx); }fxx()
下面这个写法也会报错,因为函数的参数存在独自的作用域,在这个参数作用域内,执行后果为 let xx = xx
,给xx
赋值一个未声明的变量xx
报错。(暂时性死区)
如果函数的默认参数是函数,该函数的作用域也要遵循这个规定。
let foo = 'out'function bar(func = () => foo){ let foo = 'come' console.log(func()); }bar() // out
这个例子中,函数的参数是func
默认值是一个匿名函数,返回值为变量foo
,因为函数参数这里造成一个独自的作用域,在这个作用域外面并没有定义变量foo
,所以foo
会指向外层全局变量foo
。如果去掉全局变量foo='out'
报错,赋值了一个未声明的变量。
利用
能够利用这个个性写一个参数默认值谬误抛出,如果参数并未传参则抛出一个谬误。
function throwErr(){ throw new Error('参数不得省略') } function omits(mustfn = throwErr()){ return mustfn }omits(); // 未传参抛出谬误 : 参数不得省略
调用omits
函数未传参数,该函数就会默认调用throwErr()
函数并抛出谬误。
如果将参数默认值设置为 undefined
则示意该参数是能够省略的。
rest参数
argumentsarguments
能够取得函数的参数值以及函数信息(name、length
)等
function au(arr){ console.log('arguments:',arguments); } au(2,1,4,3)
能够通过数组办法对函数参数进行操作,例如排序。arguments
对象不是数组,而是一个相似数组的对象,为了应用数组的办法,必须应用Array.from
先将其转为数组。
function au(arr){ // 通过数组办法对函数参数进行排序 return Array.from(arguments).sort(); }console.log(au(2,1,4,3)) // [1,2,3,4]
rest参数ES6
提供了rest
参数,语法:(...变量名
),其实就是残余运算符,通过rest
参数就能够很容易的对函数参数进行操作,并且rest
的参数是一个真正的数组。
// resy参数(残余运算符)function residue(...val){ console.log(val); // [1,2,3] }residue(1,2,3)
rest
参数(残余运算符)只能放到最初一位
,否则报错
// function residue2(...val,b){} // 残余运算符不是最初一位,报错function residue3(c,...val){ console.log(c,val); // 1 [2,3,4,5] }residue3(1,2,3,4,5)
下面arguments
实现的参数排序,应用rest
能够很轻松的做到,并且语义更强,更不便浏览。
let au2 = (...val) => val.sort()console.log(au2(2,1,4,3)); // [1, 2, 3, 4]
严格模式
ES5
开始,函数外部能够设定为严格模式: function s(){ 'use strict'// 严格模式 }
// es5严格模式function s(){ 'use strict' // 严格模式 // 代码.....}
ES6
做了批改,规定只有函数参数应用了默认值、解构赋值、扩大运算符,那么函数外部就不能显示设定为严格模式,否则报错。
// es6严格模式 报错,因为设置了函数默认值function s2(a,b = a){ 'use strict' // 代码.....}
// 报错,应用了解构赋值const s3 = function({a,b}){ 'use strict'}
// 报错,应用了残余运算符const s4 = (...a) => { 'use strict'}
es6
这样设置的起因是,函数外部的严格模式应该同样实用于函数体和函数参数,然而,函数执行的时候会先执行参数,再执行函数体,这样就有一些不谨严的状况,只有函数体中能力晓得参数是否应该以严格模式执行,然而函数的参数确是先执行,所以es6
批改了函数参数对于严格模式的行为。
function s5(val = 070){ 'use strict' return val}s5() // 报错
这一段,函数的默认值是八进制070
,严格模式下不能应用前缀0
示意八进制,所以报错。
但实际上
是因为函数设置了默认参数的起因,函数先执行参数,再进函数体,因为es6
限度,报错。
有两种办法能够躲避这种限度
第一种:设置全局严格模式
'use strict'function s6(val = 100){ console.log(val);}s6() // 100
第二种办法:把函数嵌套在一个无参数的立刻执行函数里
const s7 = () => { 'use strict' let a; return (function(val = 200){ return val })()}console.log(s7());
匿名函数的调用办法:在上述例子(function(val = 200){return val})()
中,将整个return
的函数用()
套起来,尾部加一个()
调用即可,()
在函数中代表调用。
案例源码:https://gitee.com/wang_fan_w/es6-science-institute
如果感觉这篇文章对你有帮忙,欢送点亮一下star哟