我们习惯将 var a = 2; 看作一个声明,而实际上JavaScript引擎并不这么认为。他将 var aa = 2 当作两个单独的声明,第一个是编译阶段的任务,第二个则是执行阶段的任务。

——《你不知道的Js》

变量提升

变量提升的概念已经为大家所熟知,简单来讲就是在代码执行前编译器会将变量的声明提升至其所在作用域(不是全局作用域)的顶端。看一个简单的例子。

如果不存在变量提升,很显然这行代码会给我们抛出一行错误  ReferenceError : a is not defined . 因为我们还没有定义 a 就使用了它。

由于存在变量声明提升,通过预编译对 a 的声明已经提升至最前,于是这里打印变量 a 的值就不会抛出 ReferenceError ( a is not defined )异常。而是打印出了 a 的值 undefined

为什么 a 为 undefined ? 这过程中还有一些细节需要注意。比如赋值与声明提升的先后关系。

undefined 表明 a 处于未赋值状态。说明了变量的赋值操作并未随着变量声明的提升而被提升,而是仍被留在原地。等同于下图。

函数声明提升

跟变量声明的提升一样,只不过声明的不再是变量而是一个函数了 var a  = >  function a(){...} 。还是来看例子。

由于存在函数声明提升,函数 foo 被正常执行打印出 a 的值为2。但这里同样有一个细节需要注意。

这里看到,函数声明会被提升,但函数表达式并不会。其中的道理跟上面的变量赋值是一样的。对变量 foo 的声明首先被提升,将一个匿名函数赋值给变量 foo 的操作还被丢在原地。像下面这样。

执行到 foo() 时,这里的 foo 只是一个值为 undefined 的小变量,还未被改变为函数呢。对一个 undefined 进行函数调用当然要抛出 TypeError 错误。

说到这里,还有一种具名的函数表达式(非匿名函数表达式),常常被人(我)误解。看例子。

为什么会出现 ReferenceError ? 先从函数的声明方式说起。函数有且只有两种声明方式。

  1. 一般函数声明:function foo(){ }
  2. 函数表达式声明:var foo = function(){ }; 等号后面必须为匿名函数

对于 var foo = function bar(){ }; 这种具名函数表达式声明函数的方式等同于普通函数表达式。但此时的 bar 仅仅作为 foo() 的一个内部属性,这就是上例中抛出 ReferenceError 的原因。

bar 作为 foo() 的内部属性只可以在 foo() 内部访问,于是上图例中返回了 bar() 函数。 在函数外部调用局部变量 bar 就一定会出现 ReferenceError 错误。

优先级问题

一般存在两个优先级问题:

  1. 函数的声明提升优先级高于同名变量声明提升。

     >>>  

  由此可见,无论在什么时候函数声明总是会被提升到普通变量之前。另外,重复的 var 声明会被忽略(严格模式下,let 和 const 不可重复声明,抛出 SyntaxError ),但出现在后面重复的函数声明会覆盖前面的。

  2. 函数形参高于同名局部变量。

  之前我还从没注意过这个问题,直到昨天做了一道题qwq。我先来简化一下原题便于理解他们的优先级问题。

      >>>   

  函数内部局部变量 foo 声明提升到所在作用域顶部后,此时它的值应该为 undefined 。像这样。

  

  但打印 foo 值却显示为1。说明此时打印 foo 实际上是函数的形参,也同时说明了函数的形参是优先于函数局部同名变量的。

  (形参实际上是函数内部自动创建的新变量,这样就相当于两个重复声明后面的声明被忽略,优先级关系也就不难理解了)

  接下来上原题啦,其实很简单。不多做解释。但如果不清楚他们的优先级关系就会做错喔。

  

  最后,重复命名可能会导致一些我们难以掌控的事情发生,所以尽量不要在同一作用域中进行重复定义。

  --End--

转载于:https://www.cnblogs.com/qimeng/p/7064032.html

JS笔记(一):声明提升相关推荐

  1. JS作用域理解(声明提升)

    1.JS解析步骤: a.预解析 将变量声明提升: 将函数声明及函数内容提升,可以理解成原来位置的函数在解析代码时已经提到代码初始位置: 块内的变量声明和函数声明也会被提升,例如if语句 遇到重名,只留 ...

  2. JS 作用域与变量提升---JS 学习笔记(三)

    你知道下面的JavaScript代码执行时会输出什么吗? var foo = 1; function bar() {if (!foo) {var foo = 10;}console.log(foo); ...

  3. Js 变量声明提升和函数声明提升

    Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...

  4. JS变量(声明)提升和函数声明提升

    目录 一.概念理解 1.变量声明提升 2.函数声明提升(又叫函数提升) 变量提升和函数提升的优先级 小结: 一.概念理解 变量提升:在当前作用于中,js代码自上而下执行之前,浏览器会把所有带var/f ...

  5. js笔记(一)js基础、程序结构、函数

    大标题 小节 一.js 基础 1. javascript的组成: 2. 运行js: 3. 打印信息: 4. 关键字var: 5. js中的数据类型: 6. NaN(not a number): 7. ...

  6. js 变量、函数提升

    js 变量.函数提升 先简单理解下作用域的概念,方便对变量与函数提升的概念的理解 function foo() {var x = 1;if (x) {var x = 2;}console.log(x) ...

  7. ES5和ES6中的变量声明提升

    ES5和ES6中的变量声明提升 Example1: a=2; var a; console.log( a ); //结果为2 Example2: console.log( a ); //结果是unde ...

  8. Javascript——声明提升(函数、变量提升)

    文章目录 一. 声明提升 1.1 示例讲解(变量提升) 1.2 示例讲解(函数提升) 二.解决方案 2.1 使用赋值 详解 三.exercise 一. 声明提升 声明提升是JavaScript中的一个 ...

  9. 菜鸟学习笔记:Java提升篇12(Java动态性2——动态编译、javassist字节码操作)

    菜鸟学习笔记:Java提升篇12(Java动态性2--动态编译.javassist字节码操作) Java的动态编译 通过脚本引擎执行代码 Java字节码操作 JAVAssist的简单使用 常用API ...

最新文章

  1. hdu1960 最小路径覆盖
  2. Linux命令行性能检测工具
  3. Java agent初探
  4. 学习响应式BootStrap来写融职教育网站,Bootsrtap第十三天讲师列表栏目
  5. 移动开发技术新趋向(三)
  6. php 信号量 关闭,php 信号量
  7. php csrf攻击 xss区别,XSS与CSRF攻击及防御方法
  8. 输入一个三位正整数,输出百位数,十位数,个位数
  9. pythonmatplotlib怎么设置曲线_python – Matplotlib的“symlog”选项:如何防止曲线“回来”?...
  10. 英特尓祭出开挖数据价值的“六脉神剑”!
  11. 影响工业镜头成像效果的两大技术指标
  12. Python反向列表
  13. C# 英文系统上中文 string 显示乱码
  14. async与defer
  15. 百度UEditor图片上传、SpringMVC、Freemarker、Tomcat、Nginx、静态资源
  16. RotateMenu简单地旋转菜单控件《IT蓝豹》
  17. 【山外笔记-计算机网络·第7版】第10章:计算机网络重要概念
  18. unity中3D数学相关类、属性、方法、用途总结+超级综合的案例
  19. Echarts之饼图
  20. 多重网格法-松弛迭代法-二维泊松方程-python实现

热门文章

  1. LomoX 桌面UI框架更新,增加资源管理
  2. uva 10183 How many Fibs?
  3. android level list,Android Drawable (levle List selector layer List)
  4. apply()智用:需要几个参数但只有一个参数数组
  5. Swing基础知识(更新中)
  6. Python 中常见的配置文件写法
  7. leetcode--最长回文子串--python
  8. Visual Paradigm 教程[UML]:如何使用刻板印象和标记值?(下)
  9. 创建mysql数据库,在新数据库中创建表,再尝试删除表
  10. Fedora 提出统一流程,弃用上千 Python 2 软件包更可控