记录自己阅读《javascript高级程序设计》的读书笔记。
var声明:
function foo() { console.log(age); var age = 26; } foo(); // undefined 之所以不会报错,是因为 ECMAScript 运行时把它看成等价于如下代码: function foo() { var age; console.log(age); age = 26; } foo(); // undefined
let声明
if (true) { let age = 26; console.log(age); // 26 } console.log(age); // ReferenceError: age 没有定义
function test() { var message = "hi"; // 局部变量 } test(); console.log(message); // 出错!
function test() { message = "hi"; // 全局变量 } test(); console.log(message); // hi
function foo() { var age = 16; var age = 26; var age = 36; console.log(age); } foo(); // 36
var name; var name; let age; let age; // SyntaxError;标识符 age 已经声明过了
const person = {}; person.name = 'Matt'; // ok
var name = 'Matt'; console.log(window.name); // 'Matt' let age = 26; console.log(window.age); // undefined
for (var i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // 你可能以为会输出 0、1、2、3、4 // 实际上会输出 5、5、5、5、5 for (let i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } // 会输出 0、1、2、3、4
原因:
1.使用var声明时,所有的迭代变量保存的都是退出循环的值,所以是5,而使用let声明,js引擎后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循 环执行过程中每个迭代变量的值。
2.setTimeout()属于异步程序,在js事件循环机制中,所有的同步程序都在执行栈中顺序执行。如果异步程序有返回结果,便将异步程序放到任务队列中。当所有的同步程序执行完成后,便将异步程序依次放入执行栈中执行。这也就是为什么var声明输出的结果会是退出循环的值,因为同步程序已经结束,i=5退出循环。