{
let a=0;
var b=1;
}
// console.log(b);
// console.log(a) //a is not defined
for(let i=0;i<10;i++){
// console.log(i);
}
//1.变量的局部性(作用域)
var a = [];
for(let i=0;i<10;i++){
a[i] = function () {
console.log(i)
}
}
// a[5]();
for(let i=0;i<3;i++){
// console.log(i);
let i = ‘abc‘;
// console.log(i);
}
//2.不存在变量提升
// console.log(foo);
var foo = ‘123‘;
// console.log(tar); //在es6中不存在变量提升
let tar = ‘131‘;
//3.暂时性死区(temporal dead zone,简称 TDZ)
//ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,
// 从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错
// var tmp = ‘123‘;
if(true){
// tmp = 123;
// let tmp;
}
if(true){
// var tmp = "123";
// console.log(tmp);
//
// let tmp;
// console.log(tmp);
//
// tmp = 123;
// console.log(tmp);
}
//上面代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”。
//“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。
// typeof x;
// let x;
//作为比较,如果一个变量根本没有被声明,使用typeof反而不会报错。
typeof undefined_number;
// function bar(x=y,y=2) {
// return [x,y];
// }
//
// bar();
function bar(x=2,y=x) {
return [x,y];
}
bar();
// var x = 1;
//
// let x =x;
//ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了
// 减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料
// 之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,
// 避免此类错误就很容易了
//总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变
// 量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出
// 现,才可以获取和使用该变量。
//4.不允许重复声明
// function a() {
// let a=0;
// let a=10;
// }
// function func(argc) {
// let argc = 0; //将会报错
// }
function func(argc) {
{
let argc = 10; //将不会报错
}
}
//5.块作用域
//在我们的es5中会出现下面的情况,
// var tmp = new Date();
//
// function f() {
// console.log(tmp);
// if (false) {
// var tmp = ‘hello world‘; //在这里会出现变量提升,会在上面先声明一个tmp
// }
// }
//
// f(); // undefined
// var s = ‘hello‘;
//
// for (var i = 0; i < s.length; i++) {
// console.log(s[i]);
// }
//
// console.log(i); // 5 //在这里将会出现我们的变量泄露,这是很严重的
//对应到es6来
function f1() {
let tmp = 5;
if(true){
let tmp = 10;
// console.log(tmp);
}
// console.log(tmp);
}
//内外层的代码快不会相互影响,只会各自执行自己的代码,相当于下面的形式
function f1() {
{
let tmp = 5;
// console.log(tmp);
}
if(true){
let tmp = 10;
// console.log(tmp);
}
}
f1();
//es6的嵌套代码块的形式是可以出现任意的嵌套层
{{{{{let tmp = 1231;}}}}}
{{{{
// {
// let tmp = 1231;
// }
// {console.log(tmp)} //这样将不能访问
}}}}
{{{{
// let tmp = 1231;
// {console.log(tmp)} //这样将可以访问
}}}}
{{{{
{let tmp = 12313;}
let tmp = 1231;//可以在不同的嵌套层声明同样的变量
}}}}
//下面的写法是es5的IIFE的写法(当函数变成立即执行的函数表达式时,表达式中的变量不能从外部访问。)
(function () {
var tmp = 123;
}());
//下面的写法是es6的
{
let tmp = 12315;
}
//块作用域与函数声明
//ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
// if(true){
// function() {
// 这是一个在es5格式下错误的函数
// }
// }
// try{
// function() {
// 这也是一个在es5格式下错误的函数
// }
// }catch(e){
//
// }
//但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中
//声明函数,因此上面两种情况实际都能运行,不会报错。
//ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域
// 之中,函数声明语句的行为类似于let,在块级作用域之外不可引用
function f() {
console.log("I am in outside")
}
(function() {
//在es5下
// if(false){
// function f() {
// console.log("I am in inside")
// }
// }
// function f() {
// console.log("I am in inside")
// }
// if(false){
//
// }
//es6规定
//允许在块级作用域内声明函数。
//函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
//同时,函数声明还会提升到所在的块级作用域的头部。
//注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实
// 现不用遵守,还是将块级作用域的函数声明当作let处理。
f();
}());
// // 浏览器的 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 环境
// 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 = ‘12312‘;
function t() {
console.log("123156");
}
}
{
let a = ‘12312‘;
let t = function() {
console.log("123156");
}
}
//另外,还有一个需要注意的地方。ES6 的块级作用域允许声明函数的规则,
// 只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
‘use strict‘
if(true){
// noinspection JSAnnotator
function s() {}
}
‘use strict‘
if(true)
// noinspection JSAnnotator
function s() {}
原文:https://www.cnblogs.com/linuxsecurity/p/9863755.html