Javascript作用域和变量提升笔记
最近读了一篇有关js作用域和变量升级的文章,对其理解更加渗透,传送门在此。
总结知识点如下:
1. 在代码运行前,函数声明和变量定义通常会被解释器移动到其所在作用域的最顶部
需要注意:变量的上升(Hoisting)只是其定义上升,而变量的赋值并不会上升
2. JavaScript是一种函数级作用域,if中并没有独立维护一个模块。
C,C++,C#和Java都是块级作用域语言,js想实现类似的块级作用域效果是用闭包。
但ES6中let声明存在块级作用域。但是let
不像var
那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。
3. 构建函数 function foo () {} 与 var foo = function () {}的区别:
function foo () {} 函数声明,函数本身也是变量,变量上升,上升整个函数
var foo = function () {} 函数表达式,是将一个匿名函数赋值给一个变量,变量上升,只上升var foo; 然后是个赋值的过程
掌握了这些知识点就可以理解这几个例子了😃:
1.
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar();
alert的是10,等同于以下代码
var foo; foo = 1; function bar() { var foo; if (!foo) { foo = 10; } alert(foo); } bar();
2.
var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a);
alert的是1, 等同于以下代码
var a = 1; function b() { function a() {} a = 10; // 这时候的赋值,其实是把函数b里面函数a变成了数值 return; } b(); alert(a);
3.
function test() { foo(); // TypeError "foo is not a function" bar(); // "this will run!" var foo = function () { alert("this won't run!"); } function bar() { alert("this will run!"); } } test();
foo()报错,bar()可以执行,是因为,其代码相当于
function test() { var foo; function bar() { alert("this will run!"); } foo(); bar(); foo = function () { alert("this won't run!"); } } test();
4.
console.log(foo); // 输出undefined console.log(bar); // 报错ReferenceError var foo = 2; let bar = 2;
5.
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }