1.let和const不存在变量提升机制

创建变量的六种方式中:var/function有变量提升,而let/const/class/import都不存在这个机制


2.var允许重复声明,而let是不允许的

在相同的作用域中(或执行上下文中)

  • 如果使用var/function关键词声明变量并且重复声明,是不会有影响的(声明第一次之后,之后再遇到就不再重复声明了)
  • 但是使用let/const就不行,浏览器会校验当前作用域中是否已经存在这个变量了,如果已经存在了,则再次基于let等重新声明就会报错
// => 在浏览器开辟栈内存供代码自上而下执行之前,不仅有变量提升的操作,还有很多其它的操作 => “词法解析”或者“词法检测”:就是检测当前即将要执行的代码是否会出现“语法错误 SyntaxError”,如果出现错误,代码将不会再执行(第一行都不会执行)
console.log(1); // => 这行代码就已经不会再被执行了
let a = 12;
console.log(a);
let a = 13;  // => Uncaught SyntaxError: Identifier 'a' has already been declared
console.log(a);
// => 所谓重复是:不管之前通过什么办法,只要当前栈内存中存在了这个变量,我们使用let/const等重复再声明这个变量就是语法错误
console.log(a);
var a = 12;
let a = 13; // => Uncaught SyntaxError: Identifier 'a' has already been declared
console.log(a);

3.let能解决typeof检测时出现的暂时性死区问题(LET比VAR更严谨)

http://es6.ruanyifeng.com/#docs/let

console.log(a); // => Uncaught ReferenceError: a is not defined

// 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”
console.log(typeof a); // => "undefined"  这是浏览器的BUG,本应该是报错的,因为没有a(暂时性死区)

console.log(typeof a); // => Uncaught ReferenceError: Cannot access 'a' before initialization
let a;

if判断中的变量提升

// [PROPERTY] in [OBJECT] 验证当前属性是否属于这个对象   hasOwnProperty?
let obj = {
	name: '吴振宇',
	age: 21,
	GF: null
};
console.log("name" in obj); //  =>  TRUE  
console.log("GF" in obj); //  =>  TRUE  
console.log("BF" in obj); //  =>  FALSE



// -----------------------------------------------------


/*
 * 全局作用域
 *   1.变量提升  
 *     不管条件是否成立都要进行变量提升
 *     var a;  //  =>  创建一个全局变量a    =>  window.a
 *   2.代码执行
 */
console.log(a); //  =>  undefined
if (!('a' in window)) { //  =>  'a' in window    =>  TRUE
	var a = 13;
}
console.log(a); //  =>  undefined


// 变体
console.log(a); // 报错
if (!('a' in window)) { 
    let a = 13; // a 是块级作用域的变量,外面不能使用 
    console.log(a) // 13
}
console.log(a); // 报错



// -----------------------------------------------------



/*
 * 全局作用域
 *   1.变量提升  
 *     但是做函数的有特殊性:在老版本浏览器中,确实不论条件是否成立,函数也是提前声明或者定义的,但是新版本浏览器中,为了兼容ES6严谨的语法规范,条件中的函数在变量提升阶段只能提前声明,不能提前定义
 *     function fn;
 *   2.代码执行
 */
// 这个不作为重点
console.log(fn); //  =>  undefined
// fn(); //  =>  Uncaught TypeError: fn is not a function
if ('fn' in window) { //  =>  TRUE
	// 条件成立,进来后的第一件事是给FN赋值,然后在代码执行
	fn(); //  =>  "哈哈哈"
	function fn() {
		console.log('哈哈哈');
	}
}
fn(); //  =>  "哈哈哈"




// -----------------------------------------------------



/*
 * 全局作用域
 *   1.变量提升 
 *   2.代码执行
 */
f = function () {return true;}  //  =>  window.f=...
g = function () {return false;}
~function () {
	/*
	 * 函数执行会形成一个私有作用域
	 *   1.变量提升  function g,只声明,不赋值,默认值是undefined
	 *   2.代码执行
	 */
    if (g() && [] == ![]) { //  =>  Uncaught TypeError: g is not a function
        f = function () {return false;}
        function g() {return true;}
    }
}();
console.log(f());
console.log(g());


// --------------------------------


//   =>   自执行函数:前面加的()或者!、-、~、+只有一个目的,让语法符合而已
//   =>   自执行函数本身不进行变量提升(没名字)
(function(n){})(10);
~function(n){}(10);
-function(n){}(10);
!function(n){}(10);
+function(n){}(10);