JavaScript变量提升的本质
2024-09-15 10:57:45
变量提升
先说三句总结性的话:
let 的「创建」过程被提升了,但是初始化没有提升。
var 的「创建」和「初始化」都被提升了。
function 的「创建」「初始化」和「赋值」都被提升了。
所以,我们要注意,这三种变量提升,含义是不同的。
变量提升的规律
在进入一个执行上下文后,先把 var 和 function 声明的变量前置,再去顺序执行代码。
PS:作用域分为全局作用域和函数作用域,用var声明的变量,只在自己所在的所用域有效。
我们举例来看看下面的代码。
代码 1:
console.log(fn);
var fn = 1;
function fn() {
}
console.log(fn);
相当于:
var fn = undefined;
function fn() {
}
console.log(fn);
fn = 1;
console.log(fn);
打印结果:
代码 2:
console.log(i);
for (var i = 0; i < 3; i++) {
console.log(i)
}
相当于:
var i = undefined;
console.log(i);
for (i = 0; i < 3; i++) {
console.log(i);
}
打印结果:
代码 3:
var a = 1;
function fn() {
a = 2;
console.log(a)
var a = 3;
console.log(a)
}
fn();
console.log(a);
相当于:
var a = undefined;
function fn() {
var a
a = 2
console.log(a)
a = 3
console.log(a)
};
a = 1;
fn();
console.log(a);
打印结果:
声明时的重名问题
假设a
被声明为变量,紧接着a
又被声明为函数,原则是:声明会被覆盖(先来后到,就近原则)。
PS:
如果
a
已经有值,再用 var 声明是无效的。如果
a
已经有值,紧接着又被赋值,则赋值会被覆盖。
举例1:
var fn; //fn被声明为变量
function fn() {// fn被声明为function,就近原则
}
console.log(fn); //打印结果:function fn(){}
举例2:
function fn() {} //fn被声明为function,且此时fn已经被赋值,这个值就是function的对象
var fn; //fn已经在上一行被声明且已经有值, 再 var 无效,并不会重置为 undefined
console.log(fn) //打印结果:function fn(){}
既然再var无效,但是再function,是有效的:
function fn() {} //fn被声明为function,且此时fn已经有值,这个值就是function的对象
function fn() { //此时fn被重复赋值,会覆盖上一行的值
console.log('smyhvae');
}
console.log(fn)
打印结果:
函数作用域中的变量提升(两点提醒)
提醒1:
在函数作用域也有声明提前的特性:
使用var关键字声明的变量,是在函数作用域内有效,而且会在函数中所有的代码执行之前被声明
函数声明也会在函数中所有的代码执行之前执行
因此,在函数中,没有var声明的变量都会成为全局变量,而且并不会提前声明。
举例1:
var a = 1;
function foo() {
console.log(a);
a = 2; // 此处的a相当于window.a
}
foo();
console.log(a); //打印结果是2
上方代码中,foo()的打印结果是1
。如果去掉第一行代码,打印结果是Uncaught ReferenceError: a is not defined
提醒2:定义形参就相当于在函数作用域中声明了变量。
function fun6(e) {
console.log(e);
}
fun6(); //打印结果为 undefined
fun6(123);//打印结果为123
其他题目
var a = 1;
if (a > 0) {
console.log(a);
var a = 2;
}
console.log(a);
打印结果:
1
2
上方代码中,不存在块级作用域的概念。if语句中用var定义的变量,仍然是全局变量。
顺便延伸一下,用let定义的变量,是在块级作用域内有效。
最新文章
- iOS组件化思路 <;转>;
- 洛谷P1341 无序字母对[无向图欧拉路]
- PHP 检测变量是否为空
- push notification获取device token
- Python之路 day2 初识字典
- NoSQL学习一:MongoDB下载与安装
- JavaScript基础知识(1)
- python脚本工具-1 制作爬虫下载网页图片
- [转] Java多线程发展简史
- C#操作Office.word(二)
- Solr/SolrCloud -error
- reshape2 数据操作 数据融合 (melt)
- js移动端横竖屏检测
- 实现自己的MVC AJAX框架计划
- Cenos7 部署asp.net core站点
- 源码调试debug_info 的作用和使用方法
- arcgis api for javascript 添加图层时设置标注,自定义符号
- camera理论基础和工作原理(转)
- pip 安装包提速
- 09 - JavaSE之线程
热门文章
- axios + mock.js模拟数据实现前后端分离开发的实例代码
- MongoDB基础介绍安装与使用
- javascript 学习笔记 -内部类
- Linux显示用户的ID
- unix时间戳转换成标准时间(c#)
- java 单例模式-饿懒汉模式
- 关于这个该死的报错:TypeError - &#39;undefined&#39; is not a function (evaluating &#39;_getTagName(currWindow).toLowerCase()&#39;)
- ASP.NET WebAPI String 传值问题
- SpringBoot 文件上传临时文件路径问题
- ssm+maven多模块项目整合