你不知道的javascript(1)

2018-03-20  本文已影响0人  九又四分之三o

1、作用域

1.1 编译原理

在传统编译语言的流程中,程序的一段源码在执行之前会经历三个步骤,统称为“编译”。

比起这些编译过程只有三个步骤的语言的编译器,Javascript引擎要复杂得多。例如,在语法分析和代码生成阶段有特定的步骤来对运行性能进行优化,包括对冗余元素进行优化等。

首先,JavaScript 引擎不会有大量的(像其他语言编译器那么多的)时间用来进行优化,因
为与其他语言不同,JavaScript 的编译过程不是发生在构建之前的。

对于JavaScript 来说,大部分情况下编译发生在代码执行前的几微秒(甚至更短!)的时
间内。在我们所要讨论的作用域背后,JavaScript 引擎用尽了各种办法(比如JIT,可以延
迟编译甚至实施重编译)来保证性能最佳。

简单地说,任何JavaScript 代码片段在执行前都要进行编译(通常就在执行前)。因此,
JavaScript 编译器首先会对var a = 2; 这段程序进行编译,然后做好执行它的准备,并且
通常马上就会执行它。

1.2 理解作用域

1、名词解释

1.4 异常

如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常,因为在任何相关的作用域中都无法找到它。
如果RHS查询找到了一个变量,但是你尝试对这个变量的值进行不合理的操作,比如试图对一个非函数类型的值进行函数调用,或者引用Null或者undefined类型的值中的属性,那么引擎会抛出另外一种异常,叫做TypeError。ReferenceError同作用域判别失败相关,而TypeError则代表作用域判别成功了,但是对结果的操作是不合法的。

2、提升

包括变量和函数在内的所有声明都会在任何代码执行前首先被处理。也就是声明提升。
函数跟变量声明都会被提升。其中函数会首先被提升,其次才是变量。

foo(); //1
var foo;
function foo(){
  console.log(1);
}

foo = function() {
  console.log(2);
}

会输出1而不是2.这段代码会被引擎理解为如下形式:

function foo(){
  console.log(1);
}
foo();//1
foo = function(){
console.log(2)
}

var foo尽管出现在function foo()...的声明之前,但它是重复的声明(因此被忽略了),因为函数声明会别提升到普通变量之前。
尽管重复的var 声明会被忽略掉,但出现在后面的函数声明还是可以覆盖前面的。

foo(); //3
function foo(){
  console.log(1);
}

var foo = function() {
  console.log(2);
}
function foo(){
  console.log(3);
}

ps:声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会被提升。

上一篇 下一篇

猜你喜欢

热点阅读