变量的作用域和变量提升

2023-11-04

京东面试题,面试官小姐姐给出了一道题:

var a = 100;
function test(){
    console.log(a);
    a = 10;
    console.log(a);
    console.log(this.a);
    var a;
}
test();

问我这三个会打印出来的值是什么?

好吧我这个还以为是要考我闭包的问题,后来一想是个变量提升的问题(好吧好吧,是小姐姐看我太尴尬了,就给我讲了一下)

回来研究一下这个变量的作用域和变量提升:

一、作用域:

一个变量的作用域(scope)是程序源代码中定义这个变量的区域。
全局变量拥有全局作用域,在javaScript代码中任何地方都有定义的。
然而在函数内声明的变量只是在函数内部有定义,他们是局部变量,作用域也只是在局部。

在函数体内,局部变量的优先级要高于全局变量。如果在函数体内重新声明一个与局部变量重名的变量,局部变量就会覆盖全局变量的值。
来看个例子:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        var num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:10
}
scope();
console.log(num);//输出:100

这个例子会打印三个数,分别是1,10,100;
局部变量的作用域仅仅在函数内部,出了函数体之后,局部变量就会被销毁。
在innerScope()函数中,虽然又声明了一个num,但是innerScope()中的num是局部变量,只是与全局变量的名字相同,并不是全局变量,所以,虽然在该函数中把num赋值为1,但这仅仅是一个与全局变量名称相同的一个变量而已,并没有改变全局变量的值。

再来看一个例子:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:1
}
scope();
console.log(num);//输出:100

上面这部分代码中,在innerScope()函数中,我们并没有用var来声明num,所以,在这里的num的作用域就被提升了,即我们将scope中的num的值重置了,所以在输出的时候输出的结果为嵌套作用域内的局部变量。

二、变量提升

在Javascript中,函数及变量的声明都将被提升到函数的最顶部。
在js中,变量的声明会被解析器悄悄的提升到方法体的最顶部,但是需要注意的是,提升的仅仅是变量的声明,变量的赋值并不会被提升,我们需要注意的是,函数的声明与变量的声明是不一样的。函数的函数体也会被一起提升。
函数表达式和变量表达式只是其声明被提升,函数声明是函数的声明和实现都被提升。

所以上面那个题就很好理解了。
我们再来看一下这个题:

var num="100";
function scope(){
    var num="10";
    function innerScope(){
        var num = "1";
        console.log(scope);//输出:1
    }
    innerScope();
    console.log(num);//输出:10
}
scope();
console.log(num);//输出:100
  1. 因为变量提升,a提升到最前面,声明未赋值,所以第一个就会打印undefined;
  2. 第二个在a声明之后,而且a赋值为10,所以第二个打印出来10;
  3. 第三个,因为test()是在window下调用的;this指的是test()调用的作用域,所以第三个打印100;

看一个函数提升的例子:

<script language="javascript" type="text/javascript">    
    //在全局对象中声明两个全局函数,反模式  
    function foo()  
    {  
        alert("global foo");  
    }  

    function bar()  
    {  
        alert("global bar");  
    }  

    //定义全局变量  
    var v = "global var";  

    function hoistMe()  
    {  
        alert(typeof foo); //function  
        alert(typeof bar); //undefined  
        alert(v); //undefined  

        //为什么bar函数和变量v是未定义而不是全局变量中定义的相应的函数变量呢?  
         //因为函数里面定义了同名的函数和变量,无论在函数的任何位置定义这些函数和  
         //和变量,它们都将被提升到函数的最顶部。  

        foo(); //local foo  
        bar(); //报错,TypeError "bar is not a function"

        //函数声明,变量foo以及其实现被提升到hoistMe函数顶部  
        function foo()  
        {  
            alert("local foo");  
        }  

        //函数表达式,仅变量bar被提升到函数顶部,实现没有被提升  
        var bar = function()  
        {  
            alert("local bar");  
        };  


        //定义局部变量  
         var v = "local";  
    }  

    (function()  
    {  
        hoistMe();  

    })();  

   //函数表达式和变量表达式只是其声明被提升,函数声明是函数的声明和实现都被提升。  
    /**由于函数提升的效果,hoistMe方法相当于 
    function hoistMe() 
    { 
        //函数声明,变量foo以及其实现被提升到hoistMe函数顶部 
        function foo() 
        { 
            alert("local foo"); 
        } 

         //函数表达式,仅变量bar被提升到函数顶部,实现没有被提升(同变量提升) 
        var bar = undefined; 

        //变量声明被提升 
         var v = undefined; 

        alert(typeof foo); //function 
        alert(typeof bar); //undefined 
        alert(v); //undefined 

        foo(); //local foo 
        bar(); //报错,缺少对象 

        bar = function() 
        { 
            alert("local bar"); 
        }; 

       v = "local"; 

    } 
    */  
</script>  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

变量的作用域和变量提升 的相关文章

随机推荐

  • 详解vue中diff算法

    详解vue中diff算法 vue中diff算法 作用 1 真实DOM和虚拟DOM 2 diff的比较方式 diff涉及到的函数 总结 vue中diff算法 本质 找出两个对象之间的差异 核心 子节点数组进行比较 首尾两端对比 作用 渲染真实
  • halcon——缺陷检测常用方法总结(模板匹配(定位)+差分)

    引言 机器视觉中缺陷检测分为一下几种 blob分析 特征 模板匹配 定位 差分 光度立体 halcon 缺陷检测常用方法总结 光度立体 唯有自己强大 博客园 cnblogs com 特征训练 测量拟合 频域 空间域结合 halcon 缺陷检
  • 射极跟随器实验报告数据处理_射极跟随器实验报告

    射极跟随器实验报告 由会员分享 可在线阅读 更多相关 射极跟随器实验报告 3页珍藏版 请在人人文库网上搜索 1 实验六 射极跟随器一 实验目的l 掌握射极跟随器的特性及测量方法 2 进一步学习放大器各项参数的测量方法 二 实验原理下图为射极
  • 自定义异常 raise 关键字

    目录 自定义抛出异常关键字 raise 使用raise主动引发异常 raise 关键字的用法 触发异常 自定义异常类 python从小白到总裁完整教程目录 https blog csdn net weixin 67859959 articl
  • 移动端安全通信的利器——端到端加密(E2EE)技术详解

    前言 端到端加密允许数据在从源点到终点的传输过程中始终以密文形式存在 采用端到端加密 又称脱线加密或包加密 时消息在被传输时到达终点之前不进行解密 因为消息在整个传输过程中均受到保护 所以即使有节点被损坏也不会使消息泄露 端到端加密系统与链
  • jsoncpp库使用实例

    jsoncpp与json json是什么 JSON JavaScript Object Notation 是一种轻量级的数据交换格式 它是一种文本格式 它实际上是一种独立于编程语言的数据格式 几乎所有现代编程语言都支持解析和生成JSON数据
  • C++回文子串

    回文子串 给定一个字符串 你的任务是计算这个字符串中有多少个回文子串 回文串是一个正读和反读都一样的字符串 具有不同开始位置或结束位置的回文串 即使是由相同的字符组成 也会被计为是不同的子串 输入 仅包含一个字符串 长度不会超过 1000
  • RSA私钥及公钥生成

    1 生成密钥 cmd 进入jdk的bin目录下 输入如下命令 keytool genkey alias xxxx keyalg RSA keysize 1024 storetype pkcs12 keystore D xxxx p12 会出
  • xml文件的注释展示

    xml文件的注释格式 lt 被注释的内容 gt 注释不能嵌套定义 XML可以从HTML中分离数据 即能够在HTML文件之外将数据存储在XML文档中 这样可以使开发者集中精力使用HTML做好数据的显示和布局 并确保数据改动时不会导致HTML文
  • Latex中的(左边有大括号的)方程组解决方案汇总

    CODE begin equation begin cases eq1 eq2 end cases end equation 对于不需对齐的方程组这样写比较方便 需要对齐的时候间距太大了 有时候需要对齐 这时候我用 CODE begin e
  • 欢迎来到 C# 9.0(Welcome to C# 9.0)

    C 9 0 已于 2020年11月10日 正式发布了 请点击链接转至 C 9 0 正式发布了 C 9 0 on the record 阅读最新版内容 https mp weixin qq com s b7yd5FoR6jDrhx8K 310
  • php 返回header,PHP header返回http头类型大全 header( Content-T

    php 代码库 定义编码 header Content Type text html charset utf 8 Atom header Content type application atom xml CSS header Conten
  • qt5.5.1 linux 64下载,[更新]Qt Enterprise v5.5.1正式发布[附下载]

    原标题 更新 Qt Enterprise v5 5 1正式发布 附下载 Qt最早诞生于1991年 长期以来一直以 linux平台下 最著名的开发平台 身份 在全世界开发者中享有盛誉 Qt Enterprise是目前最先进 最完整的跨平台C
  • 这个Chrome 插件,让你的GPT无比丝滑!

    ChatGPT的官网最近几天报错越来越频繁了 相信大家都发现了 一旦你离开页面时间比较久 再度返回跟它进行对话 就会出现如下报错 虽然这个报错信息以前也出现过 但现在的频率确实过高 对于每天需要使用 ChatGPT 处理大量任务的用户来说
  • 我们压缩了一批深度学习进阶“传送门”给小白

    编译 ShanLIU Chloe 笪洁琼 Harry 作者 Seth Weidman 阅读这篇文章的必要性 无论是作为行业内的从业者还是一个组织 在开始深度学习应用之前 都需要掌握两件事 1 知其然 掌握一个基础概念 知道深度学习的最新发展
  • Vue路由跳转到新页面之后,返回旧页面保持状态不变

    新项目中遇到了登录时点击用户协议 进入协议页面让用户阅读 然后返回登录页面时发现原来填写的手机号验证码全都没有了 解决方案 使用keep alive 在vue app中添加keep alive标签
  • MyBatis快速入门(四) MyBatis和Spring集成

    导入依赖包 前面介绍了MyBatis的相关知识 现在来介绍一下如何和Spring进行集成 MyBatis和Spring的集成工作是由MyBatis团队完成的 所以我们首先要先引入MyBatis和Spring的集成依赖包 这里我用的是Grad
  • 【渗透测试】Apache Shiro系列漏洞

    目录 Shiro 550 CVE 2016 4437 1 漏洞原理 2 影响版本 3 漏洞利用 Shiro 721 1 漏洞原理 2 影响版本 3 漏洞利用 Shiro认证绕过漏洞 CVE 2020 1957 1 漏洞原理 2 影响版本 3
  • 前端js调用方法的几种方式

    最近在做前端项目 因为没上vue还是原生的jq方法 所以遇到各种各样的问题 在这记录下几种前端触发的方法 1 onclick 在标签内直接写 nclick qz this 即可 然后js中写方法 2 fxbsbutton click 第一个
  • 变量的作用域和变量提升

    京东面试题 面试官小姐姐给出了一道题 var a 100 function test console log a a 10 console log a console log this a var a test 问我这三个会打印出来的值是什