Js代码分为两个阶段:编译阶段和执行阶段

Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容

包括变量声明(var a)和函数声明(function a(){})在内的所有声明都会在代码被执行前的编译阶段首先被处理

过程就好像变量声明和函数声明从他们代码中出现的位置被移动到执行环境的顶部,这个过程就叫做提升

只有声明操作会被提升,赋值和逻辑操作会被留在原地等待执行

变量声明

Js编译器会把变量声明看成两个部分分别是声明操作(var a)和赋值操作(a=2)

声明操作在编译阶段进行,声明操作会被提升到执行环境的顶部,值是undefined(表示未初始化)

赋值操作会被留在原地等待执行阶段

 var a = 2;

 function foo() {
console.log(a); //undefined
var a = 10;
console.log(a); //
} foo(); // 相当于 var a = 2; function foo() {
var a;
console.log(a); //undefined
a = 10;
console.log(a); //
} foo();

函数声明

定义函数有两种方式:函数声明和函数表达式

函数声明提升会在编译阶段把声明和函数体整体都提前到执行环境顶部,所以我们可以在函数声明之前调用这个函数

函数表达式,其实就是变量声明的一种,声明操作会被提升到执行环境顶部,并赋值undefined。赋值操作被留在原地等到执行。

 // 函数声明

 foo(); //

 function foo(){
console.log(100);
}
 // 函数表达式
baz(); // TypeError: baz is not a function var baz = function(){
console.log(200);
} //相当于 var baz; baz(); baz = function() {
console.log(200);
};

控制语句

Js中使用函数级作用域,不存在块级作用域。所有普通块中的声明都会被提升到顶部,所以控制语句对声明的控制就显得完全没有效果

 if (false) {
var a = 10;
} console.log(a); //undefined // 相当于 var a;
if (false) {
a = 10;
} console.log(a) //undefined

奇怪的函数声明

 console.log(a); //undefined

 if (false) {
function a() {
console.log(100);
}
} a(); //TypeError: a is not a function 理论上应该是100

奇怪吧??函数提升发生在所有代码执行之前,所以尽管a函数的定义过程写在了if分支中,但是理论上,它是不会影响函数声明提升的

在新版本的浏览器中会出现此问题,旧版本的浏览器中会在控制台中打印出100

这也提醒了我们尽量不要在控制语句中进行声明,会造成很多无法预知的bug

函数优先

提升操作会优先进行函数的声明

函数会首先被提升然后才是变量,重复的变量声明会被忽略,只剩下赋值操作,多个函数声明可以进行覆盖

声明的顺序是这样的:

1. 找到所有的函数声明,初始化函数体,如有同名的函数则会进行覆盖

2. 查找变量声明,初始化为undefined,如果已经存在同名的变量,就什么也不做直接略过

 //
foo(); // function foo() {
console.log(100);
} function foo() {
console.log(200);
} //
console.log(foo); //function foo(){...} function foo(){
console.log(200);
}
var foo = 100;

Js 变量声明提升和函数声明提升的更多相关文章

  1. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  2. JS 函数提升&变量提升以及函数声明&函数表达式的区别

    感谢原文作者:迟早会有猫 原文链接:https://www.cnblogs.com/SidselLoong/p/10515809.html 今天看js的变量提升问题,里面提到了函数提升.然后发现自己之 ...

  3. 【JS】函数提升变量提升以及函数声明和函数表达式的区别

    今天看js的变量提升问题,里面提到了函数提升.然后发现自己之前一直把函数声明和函数表达式弄错,导致函数提升出错 一.变量提升 console.log(a) var a=100 //undefined ...

  4. 【JS点滴】声明提前,变量声明提前,函数声明提前,声明提前的先后顺序

    声明提前,函数声明提前,好吧,老生常谈的问题了.正好,前些天在掘金看到一道关于声明提前的笔试题,那么这里就以这道题来作为本文的引子吧,代码如下: console.log(a)//? a();//? ; ...

  5. js变量的作用域、变量的提升、函数的提升

    变量的作用域在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问.在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问. ECMAScript 6 之前的 Jav ...

  6. js中变量提升(一个是变量,一个是函数表达式都会存在变量提升,函数声明不存在)

    一.变量提升 在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.上个简历的例子如: ...

  7. JS变量声明提升和函数声明提升

    JS代码在执行的时候会先找出执行代码中定义的变量和函数,对其进行声明. 例1:console.log(a); var a = 4; 此时输出undefined.a变量在执行console.log(a) ...

  8. 变量声明提升 Vs. 函数声明提升

    1. 变量声明提升 先看以下代码: 1)var in_window = "a" in window; console.log(in_window); 2)var in_window ...

  9. javascript变量声明提升和函数声明提升

    在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分. JS的解析过程分为两个阶段:预 ...

随机推荐

  1. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  2. Jquery的点击事件,三句代码完成全选事件

    先来看一下Js和Jquery的点击事件 举两个简单的例子 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...

  3. 微信公众号开发之VS远程调试

    目录 (一)微信公众号开发之VS远程调试 (二)微信公众号开发之基础梳理 (三)微信公众号开发之自动消息回复和自定义菜单 前言 微信公众平台消息接口的工作原理大概可以这样理解:从用户端到公众号端一个流 ...

  4. 浅谈我对DDD领域驱动设计的理解

    从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...

  5. KMP算法求解

    // KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> using namespac ...

  6. 数据库的快照隔离级别(Snapshot Isolation)

    隔离级别定义事务处理数据读取操作的隔离程度,在SQL Server中,隔离级别只会影响读操作申请的共享锁(Shared Lock),而不会影响写操作申请的互斥锁(Exclusive Lock),隔离级 ...

  7. arcgis api for js入门开发系列七图层控制(含源代码)

    上一篇实现了demo的地图分屏对比模块,本篇新增图层控制模块,截图如下(源代码见文章底部): 图层控制模块实现的思路如下: 1.在地图配置文件map.config.js里面配置图层目录树节点信息,作为 ...

  8. HTML5 标签 details 展开 搜索

    details有一个新增加的子标签--summary,当鼠标点击summary标签中的内容文字时,details标签中的其他所有元素将会展开或收缩. 默认状态为 收缩状态 设置为展开状态为 <d ...

  9. TCP/IP之TCP_NODELAY与TCP_CORK

    TCP/IP之Nagle算法与40ms延迟提到了Nagle 算法.这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,使用TCP_NODELAY选项可以禁止Nagl ...

  10. JVM系列-常用参数

    1.堆内存 堆内存用于存储new对象,垃圾回收器负责堆内存的管理.但Java程序实际占用的空间则由堆内存.栈内存(程序运行栈).程序计数器.常量区.代码区.本地内存等. 堆内存分为Young和Old, ...