js作用域、变量提升、函数提升

时间:2020-05-22
本文章向大家介绍js作用域、变量提升、函数提升,主要包括js作用域、变量提升、函数提升使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

先看一个题目

var foo = 1;
function bar() {
    if (!foo) {
        var foo = 10;
    }
    alert(foo);
}
bar();

alert的结果是 10

再看下一个:

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

alert结果是1

console.log(v1);
var v1 = 100;
function foo() {
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
foo();
console.log(v1);

//undefined
//undefined
//200
//100

如果以上题目都答对了,那可能接下来的内容你就不需要去看了,如果你现在有很多问号,那就继续看下去

一、作用域(scope)

C语言的一个例子:

#include <stdio.h>
int main() {
    int x = 1;
    printf("%d, ", x); // 1
    if (1) {
        int x = 2;
        printf("%d, ", x); // 2
    }
    printf("%d\n", x); // 1
}

程序依次输出了1,2,1.
C语言中,我们有块级作用域(block-level scope)。在一个代码块(一对{}花括号括起来的部分)的中变量并不会覆盖掉代码块外面的变量。

JavaScript中的表现:

var x = 1;
console.log(x); // 1
if (true) {
    var x = 2;
    console.log(x); // 2
}
console.log(x); // 2

JavaScript有函数级作用域(function-level scope)。这一点和C家族完全不同。语句块,如if语言,不创建新的作用域。仅仅函数能创建新作用域。

在JavaScript中,如果我们需要实现block-level scope,我们也有一种变通的方式,那就是通过自执行函数创建临时作用域:(闭包)

function foo() {
    var x = 1;
    if (x) {
        (function () {
            var x = 2;
            // some other code
        }());
    }
    // x is still 1.
}

上面代码在if条件块中创建了一个闭包,它是一个立即执行函数,所以相当于我们又创建了一个函数作用域,所以内部的x并不会对外部产生影响。

变量作用域
一个变量的作用域表示这个变量存在的上下文。它指定了你可以访问哪些变量以及你是否有权限访问某个变量。
变量作用域分为局部作用域和全局作用域。

全局作用域:最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的

var outerVar = "outer";
function fn(){
  console.log(outerVar);
}
fn();//result:outer

局部作用域:和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的

function fn(){
  var innerVar = "inner";
}
fn();
console.log(innerVar);// ReferenceError: innerVar is not defined

需要注意的是,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!

 function fn(){
  innerVar = "inner";
}
fn();
console.log(innerVar);// result:inner

再来看一个代码:

var scope = "global";
function fn(){
  console.log(scope);//result:undefined
  var scope = "local";
  console.log(scope);//result:local;
}
fn();

第一个输出居然是undefined,原本以为它会访问外部的全局变量(scope=”global”),但是并没有。这可以算是javascript的一个特点,只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量“提前声明”:

var scope = "global";
function fn(){
  var scope;
  console.log(scope);//result:undefined
  scope = "local";
  console.log(scope);//result:local;
}
fn();

然而,也不能因此草率地将局部作用域定义为:用var声明的变量作用范围起止于花括号之间。 javascript并没有块级作用域,javascript的作用域是相对函数而言的,可以称为函数作用域。

变量提升 函数提升
变量提升即将变量声明提升到它所在作用域的最开始的部分。在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。

概念:

  1. js的变量和函数在编译阶段会被提升到当前作用域最前面编译
  2. 函数是一等公民,优先编译函数

下面看例子

console.log(a);//function a(){}
var a = 10;
function a(){

}
console.log(a);//10

变量的声明虽然在函数声明之前,但是函数优先被编译,实际代码是

function a(){

}
console.log(a);
a = 10;
console.log(a);

这里的实际代码中是a = 10而不是var a = 10;因为函数声明不仅优先被编译了,还覆盖掉剩余的同名变量的声明。

js中创建函数有两种方式:函数声明式函数字面量式只有函数声明才存在函数提升!
继续看这个例子:

console.log(a);//function a(){}
console.log(b); // undefined
function a(){

}
var b = function(){}

它实际的执行过程

function a(){

}
var b;
console.log(a);//function a(){}
console.log(b); // undefined
b = function(){}

原文地址:https://www.cnblogs.com/SPHmomo/p/12936074.html