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"
    
    
  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/cdwp8/p/4056477.html
Copyright © 2011-2022 走看看