zoukankan      html  css  js  c++  java
  • javascript中变量声明提升(Hoisting)

    JavaScript 会提升变量声明。这意味着 var 表达式和 function 声明都将会被提升到当前作用域的顶部。

    bar();
    var bar = function() {};
    var someValue = 42;
    
    test();
    function test(data) {
        if (false) {
            goo = 1;
    
        } else {
            var goo = 2;
        }
        for(var i = 0; i < 100; i++) {
            var e = data[i];
        }
    }

    上面代码在运行之前将会被转化。JavaScript 将会把 var 表达式和 function 声明提升到当前作用域的顶部。

    // var 表达式被移动到这里
    var bar, someValue; // 缺省值是 'undefined'
    
    // 函数声明也会提升
    function test(data) {
        var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
        if (false) {
            goo = 1;
    
        } else {
            goo = 2;
        }
        for(i = 0; i < 100; i++) {
            e = data[i];
        }
    }
    
    bar(); // 出错:TypeError,因为 bar 依然是 'undefined'
    someValue = 42; // 赋值语句不会被提升规则(hoisting)影响
    bar = function() {};
    
    test();

    主意test函数中的goo=1变量, 第一次出现的时候,并没有使用var,在我们的理解中,foo被隐式的声明成了全局变量,

    但是 在后面又出现了一个 var goo=2,声明了是一个局部的变量,根据变量提升的规则,

    var goo会被提升到顶部, var goo = 'undefined' 

    所以 goo是一个局部变量。

    // 来自 Nettuts+ 的一段代码,生动的阐述了 JavaScript 中变量声明提升规则
    var myvar = 'my value';  
    
    (function() {  
        alert(myvar); // undefined  
        var myvar = 'local value';  
    })();  

     这一段代码说明了很多问题。

    var myvar ='my value';  

    (function(){  
      var myvar = undefined // 变量声明被提升到了这个位置。
        alert
    (myvar);// undefined  
       
    var myvar ='local value';  
    })();


    在《悟透Javascript》里有这样一个例子
    var myFunc = function(){
         alert('Hello');       
    }
    
    myFunc(); // 输出Hello
    
    myFunc = function(){
        alert('yeah');
    }
    
    myFunc();  第二次调用输出 yeah
    
    这没什么好奇怪的。 然后我们再看下面一段代码
    
    function myFunc(){
       alert('Hello');
    }
    
    myFunc(); // 第一次调用 输出yeah;很奇怪吧
    
    function myFunc(){
       alert('yeah');
    }
    
    myFunc(); // 还是输出 yeah!
    
    
    
    这里面还是变量申明别提前的原因,不做多解释

     引用书中原话

     原来,JavaScript 执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且,在
    同一段程序的分析执行中,定义式的函数语句会被提取出来优先执行。函数定义执行完之后,才会按顺序
    执行其他语句代码。也就是说,在第一次调用 myfunc之前,第一个函数语句定义的代码逻辑,已被第二
    个函数定义语句覆盖了。所以,两次都调用都是执行最后一个函数逻辑了。
     
         如果把这个 JavaScript 代码分成两段,例如将它们写在一个html中,并用<script/> 标签将其分成
    这样的两块

    < script >  
         function myfunc () 
        { 
            alert("hello"); 
        }; 
        myfunc();  // 这里调用 myfunc,输出 hello 
    </script >
    < script >  
         function myfunc () 
        { 
            alert("yeah"); 
        };     
        myfunc();  // 这里调用 myfunc,输出 yeah 
    </script >  



    所以总结如下:

    名称解析顺序

    JavaScript 中的所有作用域,包括全局作用域,都有一个特别的名称 this 指向当前对象。

    函数作用域内也有默认的变量 arguments,其中包含了传递到函数中的参数。

    比如,当访问函数内的 foo 变量时,JavaScript 会按照下面顺序查找:

    1. 当前作用域内是否有 var foo 的定义。
    2. 函数形式参数是否有使用 foo 名称的。
    3. 函数自身是否叫做 foo
    4. 回溯到上一级作用域,然后从 #1 重新开始。
     http://bonsaiden.github.io/JavaScript-Garden/zh/#core.eval
  • 相关阅读:
    [原创]网页级在线性能测试网站介绍
    [原创]浅谈测试团队文化
    [原创]浅谈自动化测试中的金字塔模型理解
    [原创]如何在面试时选择合适的测试人员?
    [原创]浅谈怎么写周报
    [原创]Windows下调试工具介绍
    [原创]浅谈我对持续集成的理解
    [原创]IBM AppScan工具培训
    [原创]Jenkins持续集成工具介绍
    [原创]什么是信息安全资产管理?
  • 原文地址:https://www.cnblogs.com/iu90/p/3081884.html
Copyright © 2011-2022 走看看