变量提升

2019-08-01  本文已影响0人  Artifacts

变量提升的概念

当栈内存(作用域)形成,JS 代码自上而下执行之前,浏览器首先会把所有带 var / function 关键字开头的进行提前声明或者定义,这种预先处理机制称为“变量提升”。

  1. 声明(declare):var a (默认 undefined
  2. 定义(defined):a = 12(定义就是赋值操作)
  3. 变量提升只发生在当前作用域(如开始加载页面时只对全局作用域下的进行提升,因此此时函数中存储的都是字符串而已)
  4. 在全局作用域下声明的函数或者变量是“全局变量”,在私有作用域下声明的变量是“私有变量”(带var/function的才是声明)
  5. 浏览器做过的事情不会重复第二遍,就是当代码执行遇到创建函数这部分代码时候直接跳过(因为在提升阶段就完成赋值操作)
    变量提升阶段:
console.log(a); //=> undefined,如果后面都没有声明,那么就会报错
var a = 12;

b(); //=> 1,可以直接使用,如果后面没有定义,那么会报错
function b() {
  console.log(1);
}

因为用 function 关键字声明的函数 ,在变量提升阶段已经赋好值了,所以可以在 JS 文件中的任意位置调用这个函数

var a = 12;
var b = a;
b = 13;
console.log(a);

/* var ary1 = [12,23];
var ary2 = ary1;
ary2.push(100);
console.log(ary1);
 */ 

function sum(){
    var total = null;
    for(var i = 0;i < arguments.length; i++){
        var item = arguments[i];
        item = parseFloat(item);
        !isNaN(item) ? total += item : null;
    }
    return total;
}
console.log(sum(12,23,'34','AA'))
运行机制

变量的声明会被自动移到函数或者全局代码的最顶上。移动的仅仅是declarations,变量的定义并不会随之提升,如下代码:

var date = new Date();
function fn(){
    console.log(date);
    if(true){
        var date = 'hello';
    }
}
fn();

结果并不是date的toString方法返回的结果,而是undefined,因为以上代码等价于:

// 变量声明提升
var date;
date = new Date();
function fn(){
    // 变量声明提升,但是此时未定义变量的值
    var date;
    console.log(date);
    if(true){
        date = "hello";
    }
}
fn();

但是在变量提升中还存在着一些特殊情况,因为在ES5中,变量声明、函数声明都会被提升,这就衍生出很多值得辨析的问题。

在ES6中,function *, let, class, const也会被提升,但是提升机制又与变量提升、函数提升有所区别

四大原则


在ECMAScript5中,JS只有两类作用域:全局作用域、函数作用域

// 全局变量
var i = 100;
// 函数声明,outer是一个外部函数
function outer(){
    // 访问全局变量
    console.log(i);  // 100
    // 函数声明,inner是一个内部函数
    function inner(){
        // 内部函数的内部进行了变量提升,也就是第二部分叙述的内容
        console.log(i);  // undefined
        // 这里的i是局部变量,作用域仅在函数内
        var i = 1;
        // 局部变量覆盖全局变量,或者说是函数作用域覆盖全局作用域
        console.log(i);  // 1
    }
    inner();
    // 这里的i是全局变量
    console.log(i);  // 100
}
outer();

定义变量时,如果不写var,那么就会相当于声明了一个全局变量,作用域为全局作用域;否则声明的是局部变量,作用域为函数作用域。在以上代码段中,第一行的var i = 0是全局变量,虽然它添加var,但是在全局范畴中声明,而且不在函数范围内,因此效果等同于i = 0。但是在JS编程中应该尽力避免不加var,即使真的需要全局变量,也应该在最外层作用域中使用var声明。

上一篇下一篇

猜你喜欢

热点阅读