zoukankan      html  css  js  c++  java
  • JavaScript中的作用域与函数和变量声明的提升

     

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

    bar();//解释:js没有块级作用域,if switch while等不会有块级作用域

    如果你对foo的值实际上为"10"而感到诧异的话,再看一下下面这个例子:

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

    b(); 
    alert(a);
    发现浏览器会弹出alert(1)。
    //解释:第一点是函数声明的提升会把函数的实现都提升到作用域的最顶级,上面的函数b相当于
    function b() { 
      function a() {} 
        a = 10; 
        return; 
        

    第二点是:这样的话,我们在b函数里面定义了一个a函数,a的作用域是在b函数的内部而非全局,这是对a的赋值相当于把a函数替换,作用域并不发生变化,相当于用var定义了一个a变量;所以在b函数外面输出a的时候只会去访问全局的a;
    //var a = 1; 
    function b() { 
        a = 10; 
        return; 
        function a() {} 

    b(); 
    alert(a);//报错a is undefined

    另外:如果这里的a函数不是函数声明式定义的而是变量式定义的,变量提升而函数实现并不会提升:如下:
    var a = 1; 
    function b() { 
        a = 10; 
        return; 
        a=function () {} //此处的a是全局的变量

    b(); 
    alert(a);//10
    如果是这样的话
    var a = 1; 
    function b() { 
        a = 10; 
        return; 
      var a=function () {} //此处的a是局部变量

    b(); 
    alert(a);//1
    等价于这个:
    var a = 1; 
    function b() { 
       var a;
        a = 10; 
        return; 
      a=function () {} //此处的a是局部变量

    b(); 
    alert(a);//1
    可以发现,声明语句中的赋值部分并没有被提升声明,只有名称被提升了。两种函数声明方式:
    function test() { 
        foo(); // TypeError "foo is not a function" 
        bar(); // "this will run!" 
        var foo = function () { // function expression assigned to local variable 'foo' 
            alert("this won't run!"); 
        } 
        function bar() { // function declaration, given the name 'bar' 
            alert("this will run!"); 
        } 

    test();
    这个例子中,只有包含函数体的函数声明会被提升声明。foo虽然会被提升声明,但是函数体却在执行中被赋值。以上就是提升声明时机的基本概念,看起来一点也不复杂。

    Name resolution order(JavaScript中名称解析顺序)

    名称解析顺序有4步,一般来说,如果一个名称已经被定义了,它就不会被另一个具有同名称的属性所覆盖。这也就意味着,函数声明会比变量声明优先。并不是名称的赋值操作不会被执行,只是说声明部分被忽略了而已。有些例外:
    • 原生变量arguments特立独行,包含了传递到函数中的参数。如果自定义以arguments为命名的参数,将会阻止原生arguments对象的创建。所以勿使用arguments为名称的参数。
    • 胡乱使用this标识符会引起语法错误。
    • 如果多个参数具有相同的命名,那么最后一个参数会优先于先前的,即时这个参数未定义。


    Named Function Expressions(函数命名表达式)

    你可以通过函数表达式给函数命名,语法上看起来像是函数声明,实则不是。上一段代码:
    foo(); // TypeError "foo is not a function" 
    bar(); // valid 
    baz(); // TypeError "baz is not a function" 
    spam(); // ReferenceError "spam is not defined" 
     
    var foo = function () {}; // anonymous function expression ('foo' gets hoisted) 
    function bar() {}; // function declaration ('bar' and the function body get hoisted) 
    var baz = function spam() {}; // named function expression (only 'baz' gets hoisted) 
     
    foo(); // valid 
    bar(); // valid 
    baz(); // valid 
    spam(); // ReferenceError "spam is not defined"
    
    
  • 相关阅读:
    20182316胡泊 实验5报告
    20182316胡泊 第6周学习总结
    20182316胡泊 第5周学习总结
    20182316胡泊 实验4报告
    20182316胡泊 实验3报告
    20182316胡泊 第4周学习总结
    20182316胡泊 第2,3周学习总结
    实验2报告 胡泊
    《数据结构与面向对象程序设计》第1周学习总结
    实验1报告
  • 原文地址:https://www.cnblogs.com/cdwp8/p/4056477.html
Copyright © 2011-2022 走看看