乐趣区

重读你不知道的JS (上) 第一节四章

你不知道的 JS(上卷)笔记
你不知道的 JavaScript
JavaScript 既是一门充满吸引力、简单易用的语言,又是一门具有许多复杂微妙技术的语言,即使是经验丰富的 JavaScript 开发者,如果没有认真学习的话也无法真正理解它们.
上卷包括俩节:

作用域和闭包
this 和对象原型

作用域和闭包
希望 Kyle 对 JavaScript 工作原理每一个细节的批判性思 考会渗透到你的思考过程和日常工作中。知其然,也要知其所以然。
提升
作用域同其中的变量声明出现的位置有某种微妙的联系
案例 1
a = 2;
var a;
console.log(a); // 在不了解声明提升的情况下,你可能得出结果是 undefined? 实际是 2
案例 2
console.log(a); // 你可能由于案例 1 的影响,得出 2,或者未声明便使用,ReferenceError 异常,实际上输出 undefined
var a = 2;
看看编译器怎么说:
正确的思考思路是,包括变量和函数在内的所有声明都会在任何代码被执行前首先 被处理。
编译 -> 解释 js 代码 -> 执行
只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码执行的顺序,会造成非常严重的破坏。
函数声明会被提升,但是函数表达式却不会被提升。
foo(); // 不是 ReferenceError, 而是 TypeError!
var foo = function bar() { // …
};
foo()调用执行时,foo 此时并没有赋值(如果它是一个函数声明而不 是函数表达式,那么就会赋值)。foo() 由于对 undefined 值进行函数调用而导致非法操作,因此抛出 TypeError 异常。
函数优先
函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。
一个普通块内部的函数声明通常会被提升到所在作用域的顶部,这个过程不会像下面的代 码暗示的那样可以被条件判断所控制:
foo(); // “b”
var a = true;
if (a) {
function foo() { console.log(“a”); }
}
else {
function foo() { console.log(“b”); }
}
小结
我们习惯将 var a = 2; 看作一个声明,而实际上 JavaScript 引擎并不这么认为。它将 var a 和 a = 2 当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明 (变量和函数) 都会被“移动”到各自作用域的 最顶端,这个过程被称为提升。
声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会提升。要注意避免重复声明,特别是当普通的 var 声明和函数声明混合在一起的时候,否则会引起很多危险的问题!

退出移动版