函数声明提升与变量声明提升

函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。

例题一:

     // 变量、函数声明提前
        function Foo() {
            getName = function () { alert(1); };  //函数内部没有声明getName,往外找
            return this;
        }
        Foo.getName = function () { alert(2); };
        Foo.prototype.getName = function () { alert(3); };
        var getName = function () { alert(4); };
        function getName() { alert(5); }

        //请写出以下输出结果:
        Foo.getName();
        getName();
        Foo().getName();
        getName();
        //2、4、1、1

//首先定义了一个叫Foo的函数,之后为Foo创建了一个叫getName的静态属性存储了一个匿名函数,之后为Foo的原型对象新创建了一个叫getName的匿名函数。
 //之后又通过函数变量表达式创建了一个getName的函数,最后再声明一个叫getName函数。

// 第一问
// 第一问的 Foo.getName 自然是访问Foo函数上存储的静态属性,自然是2。

//第二问
// 第二问,直接调用 getName 函数。既然是直接调用那么就是访问当前上文作用域内的叫getName的函数
// 由于变量提升
// function Foo() {
//     getName = function () { alert(1); };
//     return this;
 // }
// var getName;//只提升变量声明
// function getName() { alert(5); }//提升函数声明,覆盖var的声明

// Foo.getName = function () { alert(2); };
// Foo.prototype.getName = function () { alert(3); };
// getName = function () { alert(4); };//最终的赋值再次覆盖function getName声明

// getName();//最终输出4

//第三问
//先执行了Foo函数,然后调用Foo函数的返回值对象的getName属性函数。Foo函数的返回值是this,此处的直接调用方式,this指向window对象,遂Foo函数返回的是window对象,相当于执行 window.getName() ,
//而window中的getName已经被修改为alert(1),所以最终会输出1


//第四问
//直接调用getName函数,相当于 window.getName() ,因为这个变量已经被Foo函数执行时修改了,遂结果与第三问相同,为1

例题二:
如果将test()函数中console.log(foo());语句注释掉,foo()不会被执行。整个输出为undefined

          function test(){
              console.log(a);
              console.log(foo());

              var a = 1;
              function foo(){
                  return 2;
              }
          }
          test();
// test()执行顺序:
// 声明提前
//function foo(){return 2;}
// var a; 
// 执行console.log(a);由于此时变量只是声明,未赋值,输出undefined
// 执行console.log(foo());此时foo()被执行,输出2
// a = 1;

例题三:

         console.log(foo);
         function foo(){
             console.log('function foo');
        }
        var foo = 20;
        console.log(foo);  //20
// 以上代码执行顺序:
// 首先函数声明提升
// function foo(){console.log('function foo');}
// 接着变量声明提升
// var foo = undefined;但因为foo已经存在同名函数,此时以函数值为准,不会被undefined覆盖。
// 最后开始执行阶段代码的执行
// console.log(foo);  //function foo()
// foo = 20;

例题四:
使用函数表达式创建的函数,只有变量名会被提前声明。

           function test(){
               console.log(foo);
               console.log(bar);
               var foo = 'hello';
               console.log(foo);
               var bar = function(){
                   return 'world';
               }
               function foo(){
                   return 'hello';
               }
           }
           test();

// 执行顺序
// function foo(){return 'hello';}
// var foo;
// var bar;     //只提升了变量声明
// console.log(foo);   //function foo()
// console.log(bar);   //undefined
// foo = 'hello';      
// console.log(foo);   //hello
// bar = function(){return 'world';}

注意:
ES6中,新增的let/const,其定义的变量,也会被提前声明,但不会给赋值undefined,所以即使提升了,未赋值前也不能使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值