JavaScript 函数作用域的“提升”现象

在JavaScript当中,定义变量通过var操作符+变量名。但是不加 var 操作符,直接赋值也是可以的。
例如 : message = "hello JavaScript ! " 即定义了一个全局变量message,并赋值 “Hello JavaScript!”
--《JavaScript高级程序第三版》

如同往日一般,一群人在所谓的技术交流群里面相互斗图着。突然老王莫名的正经起来,在群里发了一道JavaScript的题目,让大家猜一猜这道题的答案。

var foo = 1;
    function bar() {
        foo = 10;
        return;
        function foo() {}
    }
    bar();
    console.log(foo);  //求控制台输出多少?

看到这到题目之后,立刻不加思索回答了“10”。
首先第一步定义一个全局变量foo = 1,然后函数执行的时候又定义全局变量 foo = 10覆盖了之前的全局变量,return之后,这个函数就直接结束, function foo {}来不及定义。因此控制台输出10;
按照在《高三》上面看到知识点推断,毫无问题,简直完美呀!

【给自己32个赞!】

但是,在把答案发出去之后。本能就感觉这道题不可能这么简单,不正经的群突然讨论正经的代码,肯定会有大坑等着人来跳。一种不好感觉涌上心头,感觉自己又要被打脸了。

赶紧打开编辑器测试一下这段代码,手哆嗦的按下F12.只见控制台下,一个耀眼的1赫然闯入眼帘。啪啪啪!!这脸又被打的,好疼呀!!

【为什么被打脸的总是我!!】

果不其然群里老王马上的在群里否决我的答案,啪的一下打了这张老脸。
不行!这个脸打了得把场子找回来,这个老王接下来肯定会揭晓答案并公布解题思路。得在他公布之前,讲答案和原因给测试出来。

经过简单的测试之后,发现原来是后面的foo,函数提升到最顶端了。所以后面foo = 10中的foo实际上是一个局部变量了。因此后面console.log(foo)时是拿不到bar函数中的局部变量foo = 10,因此只能拿到全局变量foo = 1;所以控制台输出1。

上文代码的另外一种形式:
var foo = 1;
    function bar() {
        function foo(){}
        foo = 10;
        return;
    //  function foo() {}    相当于这行代码提升到最顶部了
    }
    bar();
    console.log(foo); 

被抢了风头的老王果断的不服气呀!说我瞎猜扯犊子一厢情愿的,自己随意猜想的。
好的,下面就是开始解释我为什么说函数function foo(){}提升到最顶端。不改动老王的代码,让我们只是加两个console.log测试一下相应的输出结果。

var foo = 1;
    console.log("全局变量:foo = " + window.foo)
    function bar() {
        console.log("此时bar函数中foo =" + foo)
        foo = 10;
        console.log("bar函数中的变量是" + foo);
        console.log("全局变量foo还是:"+window.foo);
        return;
        function foo() {}
    }
    bar();
    console.log(foo); 
浏览器输出结果

通过这里可以证实我的猜想是正确的,function foo(){}直接被提升到bar()函数最顶端,然后后面foo = 10就不是再重新定义全局变量了,这里foo是一个局部变量的角色被定义出现的。因此才没有将全局变量给覆盖,而由于函数外面是不能直接拿到bar函数当中的局部变量foo,因此继续向上寻找到全局变量foo = 1.从而输出1.

这里估计联想能力丰富的小伙伴肯定会举手说,那么函数有提升的现象。那么变量也是否会有提升现象?不错!不错!!这位小伙伴联想的非常正确,学习就要多学会举一反三。

【奖励一朵小红花】

变量提升
var foo = 1;
    function bar() {
        foo = 10;
        return;
        var foo   //几乎是相同的代码,只是把 function foo  变成了   var  foo。变量也是能够提升了的!
    }
    bar();
    console.log(foo);  //还是输出1.
思考:

同样的既然变量能够提升,函数声明能够提升。那么谁升的更高呢?

function test(){
        console.log(dabang);
        function dabang(){};
        var dabang;
    }
    test();

function test1(){
        console.log(dabang);
        var dabang;
        function dabang(){};

    }
    test1();

控制台输出结果:


【大棒声明的函数那必须升的高!!!】

小结:

1、在JavaScript当中,函数作用域当中。变量和声明函数都能够提升。
2、同样提升的情况下,声明函数提升的更加高!

以上就是鄙人对于JavaScript函数作用域中“提升现象”一点简单理解,欢迎各位的大佬们指导学习。
其实js的编译就是把作用域先声明,作用域里面用到变量统一先在代码执行前分配内存,也就是先声明,function a(){}这个就直接声明了a函数,var a=function(){}这个表达式是在执行前先声明a变量值为undefined,执行到这句才把function赋值进去.

时间: 2024-12-11 11:46:49

JavaScript 函数作用域的“提升”现象的相关文章

JavaScript的作用域和提升机制

你知道下面的JavaScript代码执行时会输出什么吗? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 答案是"10",吃惊吗?那么下面的可能会真的让你大吃一惊: var a = 1; function b() { a = 10; return; function a() {} } b(); alert(a); 这里浏览器会弹出"1".怎么回事?这似乎看起

JavaScript 权威指南(4): JavaScript 的作用域和提升

JavaScript 权威指南(4): JavaScript 的作用域和提升 原文地址:http://dyy.im/4406.html 你知道下面的 JavaScript 程序执行时会输出什么值吗? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 答案是“10”,吃惊吗?那么下面的可能会真的让你大吃一惊: var a = 1; function b() { a = 10; return;

javascript中函数作用域之”提升“

javascript中函数作用域之变量提升 当我们在函数内部用关键字var声明一个变量的时候,此变量的作用域限制在当前函数. 提升:在一个作用域内部,不管一个变量用var声明的位置在哪里,这个变量属于当前整个作用域,并且在当前作用域的任何位置都可以访问它.在javascript中,这种行为/现象称之为"提升",即一个变量在一个作用域的任何位置用var声明,javascript引擎都会把这些用var声明的变量"移动"到当前作用域的开始处. 谈到javascript这种

javascript的作用域以及闭包现象

1.  词法作用域 词法作用域就是定义在词法阶段的作用域,换句话说,也就是js的作用域时在定义阶段决定的,和调用无关. 1.1 作用域沿着作用链向上查找 <!DOCTYPE html> <html> <head> <title></title> </head> <body> </body> <script type="text/javascript"> //引擎执行console

javascript函数作用域链 词法作用域

在开发语言中常见的作用域规则有  块级作用域和词法作用域 作用域 顾名思义就是起作用的区域  定义一变量后 ,可以在此范围作用的区域 一.块级作用域就是用一个块结构分割变量的访问区域  块即{ } 代表语言有C 系列语言 二.词法作用域就是变量的作用范围,在书写代码时就已经决定作用的范围,与运行时无关 特点:分割作用域只有函数 变量名提升 函数名提升 函数的声明比变量的声明优先级高 function a(){ } var a; alert(a);//打印出a的函数体 var a; functio

javascript函数作用域及this指向详解

一.先说一个简单的概念--变量提升: 通过function+函数名的方式,声明的函数,可以在代码中的任何位置调用: 通过var定义变量的方式,声明的函数,则必须在声明之后进行调用,原因就是在变量定义之前调用时,变量的值为undefined: 二.说一个特别重要的概念--函数在定义的时候(不是在调用的时候),就已经确定了函数内部自由变量的作用域: 上面的概念对于理解this指向特别重要!!! 1.首先看一个例子: bar(fn)中,fn函数执行,其this的指向毫无疑问是指向window的,但是b

JavaScript 的 作用域

在看了几本书之后的一些理解和自己的想法. 作用域,变量的作用范围 在ES6之前 变量的声明 只有var可以声明变量属于某个作用域,并且,也只有全局作用域和函数作用域. (没有var声明的变量,属于全局作用域,在全局作用域里声明的变量,函数会成为全局的属性) 所有的变量,不是全局作用域的,就是函数作用域的: 如果用var 声明变量,并且是在函数中,那么这个变量就属于这个函数,否则,属于全局变量. 变量,函数的提升 在任何一个作用域中,都存在提升: 对于一个声明,JS引擎进行处理和执行. 所谓的处理

JavaScript从作用域到闭包

作用域(scope) 全局作用域和局部作用域 通常来讲这块是全局变量与局部变量的区分. 参考引文:JavaScript 开发进阶:理解 JavaScript 作用域和作用域链 全局作用域:最外层函数和在最外层函数外面定义的变量拥有全局作用域. 1)最外层函数和在最外层函数外面定义的变量拥有全局作用域 2)所有末定义直接赋值的变量自动声明为拥有全局作用域,即没有用var声明的变量都是全局变量,而且是顶层对象的属性. 3)所有window对象的属性拥有全局作用域 局部作用域:和全局作用域相反,局部作

JavaScript变量作用域

全部变量拥有全局作用域,局部变量拥有局部作用域(这里注意函数的参数也是局部变量) 1.在函数体内,局部变量的优先级高于同名的全局变量. 我的理解就是当你同时定义了同名的局部变量和全局变量时,函数体内返回的将是局部变量的值. 例如: var scope="我是全局变量"; function checkscope(){ var scope="我是局部变量"; console.log(scope); } checkscope(); 输出:我是局部变量 这里需要注意的是,在