03月08, 2019

JS基础(5)——函数(2)——提升

在 JavaScript 里面,有一个非常重要的特性,就是提升。提升分为变量提升函数提升。而在讲解提升之前,我们需要先对作用域有一定的了解。

5-2-1 作用域

前面介绍作用域的时候,曾经给大家介绍过全局作用域以及局部作用域。事实上,在 JavaScript 里面,作用域一共有 3 种:全局作用域,函数作用域以及 eval 作用域。

全局作用域:这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境。

函数作用域:当进入到一个函数的时候,就会产生一个函数作用域。

eval作用域:当调用eval()函数的时候,就会产生一个 eval 作用域。

这里,我们先抛开最后一个 eval 作用域不说(其实这个现在用的也很少了)。我们先来看一下全局作用域和函数作用域。

上面有写到,全局作用域是默认的代码运行环境。也就是说,当我们声明了一个变量或者函数的时候,它们默认就是处于全局环境中的。

let x = 3;
function test(){
    console.log("Hello");
}

这里我们声明的x以及test()函数就是处于全局作用域里面的。

当我们调用函数的时候,这时就会又产生一个作用域,我们称之为函数作用域。

在内层函数作用域里面是可以访问到全局作用域或者外层函数作用域里面的变量或者函数的。但是反过来全局作用域或者外层函数作用域里面是不能访问到内部函数作用域里面的变量或者函数的,因为它们是局部的。

函数里面访问全局作用域里面的变量:

let x = 3;
let test = function(){
    console.log(x); // 3
}
test();

全局作用域里面访问函数作用域里面的变量:

let test = function(){
    let x = 3;
}
test(x);
// ReferenceError: x is not defined

这里在函数里面声明了变量x,全局里面访问的时候会提示没有定义。

注:在函数里面声明变量时,无论是使用的letvar,还是说是const,它们都是属于函数作用域的,外部是无法访问的。

5-2-2 变量提升

所谓变量提升,就是指在使用var关键字进行变量声明的时候,默认会将声明变量的部分提升至当前作用域的最顶上,但是注意提升的只有变量的声明部分,赋值是不会提升的

console.log(i); // undefined
var i = 10;
console.log(i); // 10

还有一点要注意的是,只有var声明的变量才具有这种特性,let或者const不存在变量提升:

console.log(i); // ReferenceError: i is not defined
let i = 10;

如果我们在函数里面声明变量时没有添加关键字,那么默认将会是在全局环境中声明一个变量:

let test = function(){
    i = 10;
}
test();
console.log(i); // 10

通过上面的代码,我们可以证明这是一个全局作用域里面的变量,但是这个变量究竟是以var的形式声明的?还是以let或者说const的方式声明的呢?

答案就是:以var的形式进行声明的,但是不具有变量提升。

这里我们可以来证明这一点。在上面的例子中,我们在外部成功访问到了在函数里面没有添加声明关键字的变量i,接下来我们来提前打印输出这个i变量,如下:

console.log(i); // ReferenceError: i is not defined
let test = function(){
    i = 10;
}
test();

可以看到这里会报错,显示的是"i is not defined",从而证明了不具有变量提升的特性。

5-2-3 函数提升

所谓函数提升,是指当我们使用字面量方式来声明一个函数的时候,此时函数的声明会提升到当前作用域的最顶端,这意味着我们可以将函数的调用书写到函数的声明之前。

test(); // Hello!
function test(){
    console.log("Hello!");
}
// 等价于
// test : pointer to  test()
// test()
// function test(){
//     console.log("Hello!");
// }

需要注意的是,仅仅只有字面量声明函数的方式才存在函数提升,如果是使用函数表达式来进行的函数声明,则不存在有函数提升的情况。

test();
let test = function(){
    console.log("Hello!");
}
// ReferenceError: test is not defined

在上面的例子中,如果我们声明函数时使用的是var关键字,这时虽然不存在函数提升,但是同样会存在变量提升,如下:

console.log(test); // undefined
var test = function(){
    console.log("Hello!");
}
console.log(test); // [Function: test]

关于本部分内容,我们会在函数进阶部分具体的来介绍其原理,所以这里只需要了解有此情况即可。

本文链接:http://www.yanhongzhi.com/post/js-basis-13.html

-- EOF --

Comments