js变量作用域--变量提升
1、JS作用域
在ES5中,js只有两种形式的作用域:全局作用域和函数作用域,在ES6中,新增了一个块级作用域(最近的大括号涵盖的范围),但是仅限于let方式申明的变量。
2、变量声明
var x; //变量声明
var x=1; //变量声明并赋值
x = 1; // 定义全局变量并赋值
3、函数声明
function fn(){}; //函数声明并定义
var fn = function(){}; // 实际上是定义了一个局部变量fn和一个匿名函数,然后把这个匿名函数赋值给了fn
4、变量提升
var tmp = new Date();
function fn(){
console.log(tmp); //Wed Jul 12 2017 22:11:56 GMT+0800 (中国标准时间)
}
fn();
a情形
var tmp = new Date();
function fn(){
console.log(tmp); //undefined
if(false){
var tmp = 'hello';
}
}
fn();
b情形
var tmp = new Date();
function fn(){
console.log(tmp); //undefined
if(true){
var tmp = 'hello';
}
}
fn();
c情形
从上面可以看到,b情形和c情形为什么不同于a情形,就是因为变量提升了(ps: c情形不同于b情形的是判断条件为true,但是这里不是看代码有没有被执行,是看变量有没有被定义)。fn函数里面定义了同名变量tmp,无论在函数的任何位置定义tmp变量,它都将被提升到函数的最顶部。等同于下面情形:
var tmp = new Date();
console.log(tmp);
function fn(){
var tmp;
console.log(tmp); //undefined
if(false){
var tmp = 'hello';
}
}
fn();
这里需要说明的是,虽然所有的申明(包括ES5的var、function,和ES6的function *、let、const、class)都会被提升,但是var、function、function *和let、const、class的的提升却并不相同!具体原因可以看这里的说明(大体的意思是虽然let,const,class也被提升了,但是却并不会被初始化,这时候去访问他们则会报ReferenceError异常,他们需要到语句执行的时候才会被初始化,而在被初始化之前的状态叫做temporal dead zone)。
因为这样的原因,推荐的做法是在申明变量的时候,将所用的变量都写在作用域(全局作用域或函数作用域)的最顶上,这样代码看起来就会更清晰,更容易看出来那个变量是来自函数作用域的,哪个又是来自作用域链。
5、重复声明
var x = 1;
console.log(x);
if(true){
var x = 2;
console.log(x);
}
console.log(x);
上面的输出其实是:1 2 2。虽然看起来里面x申明了两次,但上面说了,js的var变量只有全局作用域和函数作用域两种,且申明会被提升,因此实际上x只会在最顶上开始的地方申明一次,var x=2的申明会被忽略,仅用于赋值。也就是说上面的代码实际上跟下面是一致的:
var x = 1;
console.log(x);
if(true){
x = 2;
console.log(x);
}
console.log(x);
6、函数和变量同时提升的问题
console.log(fn);
function fn(){};
var fn = 'string';
上面的输出结果其实是: function fn(){} ,也就是函数内容。
console.log(fn);
var fn = function fn(){};
var fn = 'string';
这时输出结果就是undefined,知道上面的声明提升的道理就不难理解了。
总结:
要彻底理解JS的作用域和Hoisting,只要记住以下三点即可:
1、所有申明都会被提升到作用域的最顶上
2、同一个变量申明只进行一次,并且因此其他申明都会被忽略
3、函数声明的优先级优于变量申明,且函数声明会连带定义一起被提升
注意:
通过with语句,可以临时改变运行期上下文的作用域链,此时的对非var定义的变量进行访问,会首先访问with中对象的属性,然后才会向上顺着作用域链向上检查该属性。
js变量作用域--变量提升的更多相关文章
- js:函数与变量作用域的提升
一.要彻底理解JS的作用域和Hoisting,只要记住以下三点即可: 1.所有申明都会被提升到作用域的最顶上 2.同一个变量申明只进行一次,并且因此其他申明都会被忽略 3 ...
- JavaScript 变量作用域
一. 变量声明 变量用var关键字来声明,如下所示: 变量在未声明的情况下被初始化,会被添加到全局环境. JavaScript执行代码时,会创建一个上下文执行环境,全局环境是最外围的环境.每个函数在被 ...
- php部分(查看文件、建立站点、语法变量、变量的几个方法、“全局局部变量的调用”、static、函数参数的作用域);
浏览器查看php文件: 建立站点,浏览php文件: php的语法 <?php echo "Hello World!"; ?> 注释语法: <?php // 这是 ...
- python学习之【第九篇】:Python中的变量作用域
1.前言 Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的. 2.变量作用域 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称.Python的作 ...
- Python基础:11变量作用域和闭包
一:变量作用域 变量可以是局部域或者全局域.定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域. 全局变量的一个特征是除非被删除掉,否则它们的存活到脚本运行结束,且对于所有的函数, ...
- Python-变量、变量作用域、垃圾回收机制原理-global nonlocal
变量实现原理决定了Python使用的垃圾回收机制为变量引用计数,当这个对象引用计数为0时候,则会自动执行__del__函数回收资源, del方法只是把变量指向的对象引用计数减一而已并删除这个变量 表达 ...
- JS 函数作用域及变量提升那些事!
虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...
- JS中作用域和变量提升(hoisting)的深入理解
作用域(Scoping) javascript作用域之所以迷惑,是因为它程序语法本身长的像C家族的语言.我对作用域的理解是只会对某个范围产生作用,而不会对外产生影响的封闭空间.在这样的一些空间里,外部 ...
- js的变量作用域 ,变量提升
(function(){ a = 5; alert(window.a); var a = 10; alert(a); })(); 结果: undefined 10 代码等同于下面 var a = un ...
随机推荐
- TensorFlow架构与设计:概述
TensorFlow是什么? TensorFlow基于数据流图,用于大规模分布式数值计算的开源框架.节点表示某种抽象的计算,边表示节点之间相互联系的张量. TensorFlow支持各种异构的平台,支持 ...
- 深度学习(十) GoogleNet
GoogLeNet Incepetion V1 这是GoogLeNet的最早版本,出现在2014年的<Going deeper with convolutions>.之所以名为“GoogL ...
- C 标准库 - string.h之memcmp使用
memcmp Compare two blocks of memory. Compares the first num bytes of the block of memory pointed by ...
- Go RabbitMQ 工作队列 (二)
rabbitMQ工作队列 在之前内容中我们通过一个队列实现了消息的发送跟接收.接下来我们创建工作队列(Work Queue),用于在多个工作者之间分配耗时的任务 工作队列(任务队列)背后的核心主要是避 ...
- P2P 行业解决方案
P2P指个人与个人之间的借贷,而P2P理财是指以公司为中介机构,把这借贷双方对接起来实现各自的借贷需求.借款方可以是无抵押贷款或是有抵押贷款.而中介一般是收取双方或单方的手续费为盈利目的或者是赚取一定 ...
- google运维解密
1.运维团队与开发团队的矛盾: 运维追求业务的稳定.开发更关注新功能的添加与版本的快速迭代.但是由于业务更新,有很大可能导致故障.从本质上来说,两部门是矛盾的. deops应该是: 1.对重复性工作有 ...
- 问题集录--jquery将json转excel保持
代码如下: <html> <head> <meta http-equiv="content-type" content="text/html ...
- [转]Creating an OData v3 Endpoint with Web API 2
本文转自:https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata- ...
- ADO MFC SQL2000
对于初学VC的朋友来说,连接数据库其实是一件不容易的事情.记得我当时为了与数据库连接上,找了好多资料,上网看了好多文章,都没有解决这个问题.后 来,有个网友帮我解决了,我再次表示感谢.为了后来VC初学 ...
- 计算细胞数【BFS】
问题描述 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数. 输入格式 2行:第1行为两个整数 mm, nn, 代表矩阵 ...