美文网首页
JS当中的变量提升(预解析)

JS当中的变量提升(预解析)

作者: 蜜糖阿橙哥c | 来源:发表于2019-06-19 17:26 被阅读0次

函数和变量声明的提升

在JS中存在一个很重要的特性,函数和变量声明的提升,理解这一点对于理解我们编写的代码非常有帮助,那么什么是声明的提升呢?我们通过下面的代码来分析。

console.log(a);//①
var a = 123;
console.log(a);//②

console.log(f);//③
f();//④
function f() {
    console.log("函数声明提升");
}

①处的代码如果按照我们以前的理解,代码从上而下执行,那么在执行这行代码的时候,a还没有被声明,所以直接访问一个没有被声明的变量,程序应该报错。

但是结果却大出所料,这里得到的结果是undefined。

③处的结果也和我们最初的认识是不一样的,结果为f对应的函数对象。

造成这个结果是因为变量和函数的作用域提升的原因,什么意思呢?

JS是解释性语言,JS引擎对代码的处理分为两步:

​ 预解析处理:在代码执行之前,对代码做全局扫描,对代码中出现的变量或者函数提前声明处理;

​ 解析之后我们的代码:

var a;//提前声明,但不初始化
console.log(a);//undefined
a = 123;
console.log(a);//123

//提前声明
function f() {
    console.log("函数声明提升");
}
console.log(f);//函数对象
f();//函数声明提升

​ 调用执行:自上而下的执行代码

变量提升和作用域的关系

题1:

f();
function f() {
    console.log("1");
}
f();
function f() {
    console.log("2");
}
f();
function f() {
    console.log("3");
}

根据前面对函数声明提升的认识,结果三次都是 “3”。

预解析之后的代码:

function f() {
        console.log("3");
}
f();
f();
f();

为什么解析之后只剩下一个函数,而且是最后那一个?

因为三个函数的名称一样,后面的函数会将前面的覆盖,所以最后只剩下最后一个函数了。

题2:

console.log(a);
var a = 123;
console.log(a);
function f1() {
    console.log(a);
    var a = 456;
    console.log(a);
}
f1();
console.log(a);

直接先对代码做预解析,然后再做分析。

var a;//变量声明提升
function f1() {//函数声明提升
    var a;//变量声明提升
    console.log(a);
    a = 456;
    console.log(a);
}
console.log(a);
a = 123;
console.log(a);
f1();
console.log(a);

解析得到上面的代码结果就非常明显了,分别是:undefined 123 undefined 456 123

由于在函数内部有变量a,所以在函数中访问到的是这个局部变量,如果在函数作用域中没有变量a,那么就会跳出函数作用域来到全局作用域来查找。

声明提升的规则

声明提升是将变量或者函数的声明提升到当前作用域的最顶端。在具体使用的过程中存在以下需要注意的细节。

  1. 变量和变量同名,解析之后只存在一个当前变量的声明
console.log(a);
var a = 123;
console.log(a);
var a = 456;
console.log(a);

解析之后:

var a;
console.log(a);//undefined
a = 123;
console.log(a);//123
a = 456;
console.log(a);//456
  1. 函数和函数同名,后面的声明将前面的覆盖
f();
function f() {
    console.log("1");
}
f();
function f() {
    console.log("2");
}
f();
function f() {
    console.log("3");
}

解析之后:

function f() {
    console.log("3");
}
f();//3
f();//3
f();//3
  1. 函数和变量同名,函数声明提升,忽略变量的声明
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
function a() {}
console.log(a);

解析之后:

function a() {}
console.log(a);//函数a
var a = 123;//将前面的函数覆盖,a的值变为123
console.log(a);//123
console.log(a);//123
console.log(a);//123
  1. 如果是命名函数,则只将前面的变量声明提升,函数不动。
console.log(fn1);
function fn1() {
}
console.log(fn1);
console.log(fn2);
var fn2 = function () {
}
console.log(fn2);

解析之后:

function fn1() {
}
var fn2;
console.log(fn1);//fn1函数
console.log(fn2);//undefined
fn2 = function () {
}
console.log(fn2);//fn2函数

面试题1:

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

sum(); //1
function sum(){
    console.log(1);
}

面试题2:

console.log(a); //undefined
var a=12;
function fn(){
    console.log(a); //undefined
    var a=13;

}
fn();
console.log(a); //12

面试题3:

console.log(a); //undefined
var a=12;
function fn(){
    console.log(a);//12
    a=13;
}
fn();
console.log(a)//13

面试题4:

console.log(a);//这个就直接报错了,因为没有变量提升 a is not defined
a=12;
function fn(){
    console.log(a);
    var a = 13;
}
fn();
console.log(a)

面试题5:

var foo=1;
   function bar(){
       //不管条件是否成立,都要进行变量提升
       //这时的foo属于私有变量 给的默认值是undefined,undefined取反就为真
       if(!foo){
           var foo=10;
       }
       console.log(foo);
   }
   bar();//10

面试题6:

var n=13;
function fn(n) {
    alert(n); // 13
    var n=14;//有形参赋值了,就不在走变量提升了
    alert(n); // 14
}
fn(n);
console.log(n);//13

面试题7:

console.log(a);// undefined
a=12;
function fn(a) {
    console.log(a); //undefined
    a=13;
}
fn();//注意这里没有传值
var a;
console.log(a); //12

面试题8:

function f1() {
    if("a" in window){//带var的变量提升时不看条件成立不成立的都会提升。
        var a = 10; //函数体中声明的变量是局部变量 所以不在window
    }
    console.log(a);//undefined
}
f1();

面试题9:

if(!"a" in window){//使用var声明的全局变量会变成window成员。
    var a = 10;
}
console.log(a);//undefined

面试题10:

console.log(a, b, c);// undefined undefined undefined
var a=10,b=20,c=30;
function f(a) {
    console.log(a, b, c);// 10 undefined 30
    var b=a=c=100;      //a 和 b 是局部变量,只有c是全局变量
    console.log(a, b, c);//100 100 100
}
f(10,20);
console.log(a, b, c);// 10,20,100     

面试题11:

function foo() {
        var num = 123;
        console.log(num);//123
    }
    foo();
    console.log(num);//报错  num is not defined

面试题12:

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

面试题13:

var foo = 1;
function bar() {
   if(!foo){     //foo变量提升完是undefined  取反条件成立
       var foo = 10;  
   }
    console.log(foo);//10
}
bar();
 console.log(foo);//1

面试题14:

var arr = [1,2,3,4];
function fun(arr) {
    arr[0] = 5;
    arr = [0];       //arr开辟了一个新的地址,指针指向改变
    arr[0] = 6;      
    console.log(arr);//[6]
    return arr
}
var res = fun(arr);
console.log(res);//[6]
console.log(arr);//[5,2,3,4]

相关文章

  • JS当中的变量提升(预解析)

    函数和变量声明的提升 在JS中存在一个很重要的特性,函数和变量声明的提升,理解这一点对于理解我们编写的代码非常有帮...

  • 1-前端基本功-JS

    //预解析:js的解析器在页面加载的时候,首先检查页面上的语法错误。把变量声明提升起来。//变量值提升变量名,不提...

  • JS预解析(变量提升)

    JS预解析(变量提升) JS的正常执行顺序是从上往下依次执行,但是JS在执行之前会读取一遍JS代码 将所有变量声明...

  • js小知识点(预解析 引用 异常 严格模式)

    预解析:会预先解析一些(变量定义、函数会预解析);var a=12;只把var a提到作用域的顶部js会把变量的声...

  • JS预解析

    JS解释器运行JS分为两步:预解析、代码执行 预解析 JS解释器会把JS里面所有的var和function提升到当...

  • 预解析

    预解析是什么? 官方式: 预解析就是提前把变量或函数预先解析到它们被使用的环境中 聊天式: 预解析就是浏览器的js...

  • 预解析

    预解析: 在代码中,首先会预先解析一些(变量定义、函数会预解析); var a=12; js只把var a提到作用...

  • JavaScript预解析

    简介js作为一门解释型脚本语言,特点是边解析边执行。而预解析则是,提前解析的意思,也就是所说的变量提升。在ES6之...

  • 作用域-变量和函数提升

    变量和函数的提升可以分成两步: 1 js先预解析:把变量和函数声明提升到作用域顶端,我理解的意思是在浏览器中找一些...

  • JS中的作用域问题

    JS解析器解析步骤 第一步:寻找代码中定义的变量,函数,参数(预解析,这也是在声明变量前使用变量不报错的原因)第二...

网友评论

      本文标题:JS当中的变量提升(预解析)

      本文链接:https://www.haomeiwen.com/subject/lgzkqctx.html