es6 Dans le bloc de calcul des variables enveloppé par if. Il existe une nouvelle portée au niveau du bloc dans es6. Le code enveloppé par "{ }" est la portée au niveau du bloc ; l'instruction if et le code dans la boucle for de la fonction appartiennent tous au bloc ; portée de niveau et sont calculés dans le bloc. Dans ES6, les portées au niveau du bloc peuvent être imbriquées arbitrairement. La portée externe ne peut pas lire les variables de la portée interne ; la portée interne peut définir des variables portant le même nom que la portée externe.
L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.
La portée au niveau du bloc est nouvelle dans ES6
. La portée du bloc est enveloppée par { }
. Le { }
dans l'instruction if
et l'instruction for
appartiennent également. à la portée du bloc. ES6
中新增了块级作用域。块作用域由 { }
包裹,if
语句和 for
语句里面的 { }
也属于块作用域。
函数中的{},if语句,for循环,也是属于块级作用域,let与const定义的变量只能在作用域有效。
第一种场景:内部变量会覆盖外部变量
var time = new Date() function fx () { console.log(time) // undefined if (false) { var time = 'hello' } } fx()
{ var a = 1 console.log(a) // 1 } console.log(a) // 1 // 通过var定义的变量可以跨块作用域访问到。
第二种场景:用来计数的循环变量泄漏为全局变量
for
循环中的用 var
定义的变量在外部作用域可以访问
for (var i = 0; i < 3; i++) { } for (let j = 0; j < 3; j++) { } // 3 console.log(i); // Uncaught ReferenceError: j is not defined console.log(j);
if
语句中 var
定义的变量在外部作用域可以访问
if(true)
与if (false)
的区别
if(true)
中的赋值语句会被执行,所以 a
打印出来是 3
if(false)
中的赋值语句不会被执行,但声明的变量 var b
会由于变量提升,提升到作用域的顶层,所以打印出来是 undefined
if (true) { var a = 3 } if (false) { var b = 3 } // 3 console.log(a); // undefined console.log(b); if (true) { let c = 3 } // Uncaught ReferenceError: c is not defined console.log(c);
function fxFn () { // 这是一个块级作用域 let fx = 'fx is a great girl' if (true) { // 这是一个块级作用域 let fx = 'fx is 18 years old' } console.log(fx) // fx is a great girl } fxFn() // 块级作用域之间相互不影响
ES6 允许块级作用域的任意嵌套。
{{{{ { let fnn = 'Hello' } console.log(fnn); // 报错 }}}};
上面代码使用了一个五层的块级作用域,每一层都是一个单独的作用域。第四层作用域无法读取第五层作用域的内部变量。
{{{{ let fnn = 'Hello'; { let fnn = 'Hello' } }}}};
块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE
)不再必要了。
// IIFE 写法 (function () { var tmp = '...'; // ... }()); // 块级作用域写法 { let tmp = '...'; // ... }
ES5
规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
// 情况一 if (true) { function f() {} } // 情况二 try { function f() {} } catch(e) { // ... }
上面两种函数声明,根据 ES5
的规定都是非法的。
但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际都能运行,不会报错。
ES6
引入了块级作用域,明确允许在块级作用域之中声明函数。ES6
规定,块级作用域之中,函数声明语句的行为类似于 let
,在块级作用域之外不可引用。
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());
上面代码在 ES5
中运行,会得到“I am inside!
”,因为在 if
内声明的函数 f
会被提升到函数头部,实际运行的代码如下。
// ES5 环境 function f() { console.log('I am outside!'); } (function () { function f() { console.log('I am inside!'); } if (false) { } f(); }());
ES6
就完全不一样了,理论上会得到“I am outside!
”。因为块级作用域内声明的函数类似于 let
,对作用域之外没有影响。
但是,如果你真的在 ES6
浏览器中运行一下上面的代码,是会报错的,这是为什么呢?
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
上面的代码在 ES6
浏览器中,都会报错。
原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式
var
,即会提升到全局作用域或函数作用域的头部。注意,上面三条规则只对 ES6
的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作 let
处理。
根据这三条规则,浏览器的 ES6
环境中,块级作用域内声明的函数,行为类似于 var
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { var f = undefined; if (false) { function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
// 块级作用域内部的函数声明语句,建议不要使用 { let a = 'secret'; function f() { return a; } } // 块级作用域内部,优先使用函数表达式 { let a = 'secret'; let f = function () { return a; }; }
var
dans la boucle for
sont accessibles dans la portée externe 🎜// 第一种写法,报错 if (true) let x = 1; // 第二种写法,不报错 if (true) { let x = 1; }
var dans l'instruction <code>if
Les variables définies par code> sont accessibles dans la portée externe🎜🎜🎜La différence entre if(true)
et if (false)
🎜🎜a
s'imprime sous la forme 3
if( false) L'instruction d'affectation dans
ne sera pas exécutée, mais la variable déclarée var b
sera promue au niveau supérieur de la portée en raison de la promotion de la variable, elle est donc imprimée comme undefined
// 不报错 'use strict'; if (true) { function f() {} } // 报错 'use strict'; if (true) function f() {}
IIFE
anonyme) n'est plus nécessaire. 🎜rrreee🎜🎜🎜Déclaration de portée et de fonction au niveau du bloc🎜🎜🎜ES5
stipule que les fonctions ne peuvent être déclarées que dans la portée de niveau supérieur et la portée de la fonction, pas dans le bloc Déclaration de portée de niveau-niveau. 🎜rrreee🎜Les deux déclarations de fonctions ci-dessus sont illégales selon ES5
. 🎜🎜Cependant, les navigateurs ne respectent pas cette règle. Afin d'être compatibles avec l'ancien code, ils prennent toujours en charge la déclaration de fonctions dans des étendues au niveau du bloc. Par conséquent, les deux situations ci-dessus peuvent réellement s'exécuter sans signaler d'erreurs. 🎜🎜ES6
a introduit la portée au niveau du bloc, permettant explicitement de déclarer les fonctions dans la portée au niveau du bloc. ES6
stipule que dans la portée au niveau du bloc, les instructions de déclaration de fonction se comportent comme let
et ne peuvent pas être référencées en dehors de la portée au niveau du bloc. 🎜rrreee🎜Lorsque le code ci-dessus est exécuté dans ES5
, vous obtiendrez "Je suis à l'intérieur !
" car la fonction déclarée dans <code>if
f sera promu à la tête de la fonction, et le code en cours d'exécution est le suivant. 🎜rrreee🎜ES6
est complètement différent. En théorie, vous obtiendrez "Je suis dehors !
". Étant donné que les fonctions déclarées dans la portée au niveau du bloc sont similaires à let
, elles n'ont aucun effet en dehors de la portée. ES6
, une erreur sera signalée. Pourquoi ? 🎜rrreee🎜Le code ci-dessus signalera une erreur dans le navigateur ES6
. 🎜🎜Il s'avère que si les règles de traitement des fonctions déclarées dans la portée au niveau du bloc sont modifiées, cela aura évidemment un grand impact sur l'ancien code. Afin d'atténuer les problèmes d'incompatibilité qui en résultent, ES6 stipule que les implémentations de navigateurs ne peuvent pas se conformer aux réglementations ci-dessus et avoir leur propre comportement🎜var
, c'est-à-dire qu'elle sera promue en tête de la portée globale ou de la portée de la fonction. ES6
. Les implémentations dans d'autres environnements n'ont pas besoin d'être respectées. Les déclarations de fonctions au niveau du bloc doivent toujours être traitées. comme let
handle. 🎜🎜Selon ces trois règles, dans l'environnement ES6
du navigateur, les fonctions déclarées dans la portée au niveau du bloc se comportent de la même manière que les variables déclarées dans var
. Le code qui s'exécute réellement dans l'exemple ci-dessus est le suivant. 🎜rrreee🎜Considérant que le comportement provoqué par l'environnement est trop différent, il convient d'éviter de déclarer des fonctions dans une portée au niveau du bloc. Si cela est vraiment nécessaire, il doit être écrit sous forme d'expression de fonction au lieu d'une instruction de déclaration de fonction. 🎜// 块级作用域内部的函数声明语句,建议不要使用 { let a = 'secret'; function f() { return a; } } // 块级作用域内部,优先使用函数表达式 { let a = 'secret'; let f = function () { return a; }; }
如果没有大括号,JavaScript
引擎就认为不存在块级作用域。
// 第一种写法,报错 if (true) let x = 1; // 第二种写法,不报错 if (true) { let x = 1; }
上面代码中,第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。
函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。
// 不报错 'use strict'; if (true) { function f() {} } // 报错 'use strict'; if (true) function f() {}
【推荐学习:javascript视频教程】
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!