JavaScript 作用域、变量提升
JavaScript 作用域
- JavaScript 作用域
- JavaScript 局部作用域
- JavaScript 全局变量
- JavaScript 变量生命周期
- 函数参数
- HTML 中的全局变量
- ES6中的变量和作用域
- 通过let和const决定块作用域
- const创建不可变的变量
- JavaScript 变量提升
- JavaScript 初始化不会提升
- 在头部声明你的变量
你越是认真生活,你的生活就会越美好
——弗兰克·劳埃德·莱特
《人生果实》经典语录
JavaScript 作用域
作用域
是可访问变量
的集合。
在 JavaScript 中, 对象和函数
同样也是变量。
在 JavaScript 中, 作用域为可访问变量,对象,函数的集合
。
JavaScript 函数作用域
: 作用域在函数内修改。
JavaScript 局部作用域
变量在函数内声明
,变量为局部作用域。
局部变量:只能在函数内部访问
。
// 此处不能调用 carName 变量
function myFunction() {var carName = "Volvo";// 函数内可调用 carName 变量
}
因为局部变量
只作用于函数内
,所以不同的函数
可以使用相同名称的变量
。
局部变量
在函数开始执行时创建,函数执行完后
局部变量会自动销毁
。
JavaScript 全局变量
变量在函数外
定义,即为全局变量
。
全局变量有全局作用域
: 网页中所有脚本
和函数均可使用。
var carName = " Volvo";// 此处可调用 carName 变量
function myFunction() {// 函数内可调用 carName 变量
}
如果变量在函数内没有声明
(没有使用 var 关键字),该变量为全局变量
。
以下实例中 carName 在函数内,但是为全局变量。
function myFunction() {carName = "Volvo";// 此处可调用 carName 变量
}
myFunction()
// 此处可调用 carName 变量 前提是myFunction函数执行过
console.log(carName) // Volvo
JavaScript 变量生命周期
JavaScript 变量生命周期
在它声明时初始化
。
局部变量
在函数执行完毕后销毁
。
全局变量
在页面关闭后销毁
。
函数参数
函数参数
只在函数内
起作用,是局部变量
。
HTML 中的全局变量
在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。
function myFunction() {carName = "Volvo";
}
myFunction()//此处可使用 window.carName
console.log(window.carName)
PS:
你的全局变量,或者函数,可以覆盖 window 对象的变量或者函数。
局部变量,包括 window 对象可以覆盖全局变量和函数。
ES6中的变量和作用域
通过let和const决定块作用域
let
和const
创建的变量只在块作用域中
有效。它们只存于包含它们的块中。下面演示的代码,通过let在if语句块中声明一个tmp变量。这个变量仅在if语句中有效。
function func() { if (true) { let tmp = 123; console.log(tmp); // => 123 }
}
func() // 123
console.log(tmp); // => ReferenceError: tmp is not defined
相比之下,var声明的变量
作用域的范围是函数范围内
的:
function func() {console.log(tmp) // undefined 变量声明提升 还没赋值if (true) {var tmp = 123console.log(tmp) // 123}console.log(tmp) // 123
}
func()
console.log(tmp) // Uncaught ReferenceError: tmp is not defined
块作用域意味着你可在有函数内有变量的阴影。
function func() {let foo = 5;console.log(foo) // 5if(true) {let foo = 10;console.log(foo) // 10}console.log(foo) // 5
}
func()
const创建不可变的变量
由let
创建的变量是可变的:
let foo = 'abc'
foo = 'def'
console.log(foo) // def
由const
创建的是变量是一个常量
,这个变量是不可变
的:
const foo = 'abc'
foo = 'def' // Uncaught TypeError: Assignment to constant variable.
如果一个常量指的是一个对象
,那么const并不影响常量本身的值
是否是可变的,因为它总是指向那个对象,但是对象本身仍然是可以被改变的。
const obj = {}
obj.prop = 123
console.log(obj.prop) // 123
console.log(obj) // {prop: 123}
obj = {} // Uncaught TypeError: Assignment to constant variable.
如果你想让obj
真正成为一个常量
,你必须冻结它的值
:
const obj = Object.freeze({});
obj.prop = 123;
console.log(obj) // {}
也就是说,如果const定义
的常量指向的是一个对象。这个时候,它实际上指向的是当前对象的地址。这个地址是在栈里面的,而这个真实的对象是在堆栈里面的。所以,我们使用const定义这个对象后,是可以改变对象的内容的。但是这个地址是不可以改变的
。意思也就是不可以给这个对象重新赋值,比如const obj= {}, obj = {}
,即使是这样,obj好像什么也没有改变,但还是错误的。
然而在普通模式
下,并没有报错,而obj.name = 'abc’这是完全可以的。这跟JavaScript存储引用对象的值的方式有密切的关系。
const obj = Object.freeze({})
const newObj = {}
obj.name = 'w3cplus'
newObj.name = 'damo'; console.log(obj) // {}
console.log(newObj) // {name: "damo"}
使用Babel把上面ES6的代码编译成ES5代码:
'use strict';
var obj = Ob
JavaScript 变量提升
JavaScript 中,
函数及变量的声明
都将被提升到函数的最顶部
。JavaScript 中,
变量可以在使用后声明
,也就是变量可以先使用再声明
。类
不存在变量提升
以下两个实例将获得相同的结果:
例子1
x = 5; // 变量 x 设置为 5elem = document.getElementById("demo"); // 查找元素
elem.innerHTML = x; // 在元素中显示 xvar x; // 声明 x
例子2
var x; // 声明 x
x = 5; // 变量 x 设置为 5console.log(x) // 5
要理解以上实例就需要理解 “hoisting(变量提升)
”。
变量提升
:函数声明
和变量声明
总是会被解释器悄悄地被"提升"到方法体的最顶部
。
类
不存在变量提升
new Foo() // Uncaught ReferenceError: Foo is not defined
class Foo {}
JavaScript 初始化不会提升
JavaScript 只有声明的变量会提升,初始化的不会。
实例1
var x = 5; // 初始化 x
var y = 7; // 初始化 yconsole.log(x) // 5
console.log(y) // 7
实例2
var x = 5; // 初始化 xconsole.log(x) // 5
console.log(y) // undefinedvar y = 7; // 初始化 y
实例 2 的 y 输出了 undefined,这是因为变量声明 (var y) 提升了,但是初始化(y = 7) 并不会提升,所以 y 变量是一个未定义的变量。
实例 2 类似以下代码:
var x = 5; // 初始化 x
var y; // 声明 yconsole.log(x) // 5
console.log(y) // undefinedy = 7; // 设置 y 为 7
在头部声明你的变量
对于大多数程序员来说并不知道 JavaScript 变量提升
。
如果程序员不能很好的理解变量提升,他们写的程序就容易出现一些问题。
为了避免这些问题,通常我们在每个作用域开始前声明
这些变量,这也是正常的 JavaScript 解析步骤,易于我们理解。
谢谢你阅读到了最后~
期待你关注、收藏、评论、点赞~
让我们一起 变得更强
参考
JavaScript 作用域
推荐阅读
理解js中this的指向(几条规则加例子+call,apply,bind改变this指向)
JavaScript 作用域、变量提升相关推荐
- javascript --- js中的作用域 变量提升
1 求以下函数的输出 1.1 考察点: 变量提升.this.作用域 // 考察点 作用域.this.变量提升 var a = 10 function test() {a = 100console.lo ...
- JavaScript:变量提升作用域
作用域是JavaScript中听上去感觉很简单,其实比较麻烦的一个特性,什么是作用域?我看书籍有一个相对的官方解释:作用域(scope,或译有效范围)就是变量和函数的可访问范围,即作用域控制着变量和函 ...
- JavaScript中变量提升是什么?如何实现?
在进行web前端开发的时候,我们经常会遇到变量提升的情况,那么JS在解析变量的时候是如何做到提升的呢?今天小千就来带大家了解一下. 首先在JS中涉及两种作用域的问题,那么什么是作用域呢? 作用域是代码 ...
- JavaScript hoisting(变量提升)学习总结
定义:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部. JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明. 例如一下两个例子: 例1: ...
- JavaScript之变量提升
1.什么是变量提升(Hoisting)? Javascript中执行上下文 (特别是创建和执行阶段)工作方式的一种认识,在ES6之前是找不到变量提升这个词的 "变量提升"意味着变量 ...
- JavaScript的变量提升
变量提升的表现是,无论在函数中何处位置声明的变量,好像都被提升到了函数的首部,可以在变量声明前访问到而不会报错.简单来说就是通过解析和预编译为代码的函数变量创建上下文环境,使得变量在生命前就可以访问. ...
- JavaScript变量提升机制
JavaScript变量提升机制 Js代码执行前(栈内存)还做了一件事那就是变量提升,Js会在所有var function等关键字的提前声明或者定义.. 看以下的代码: console.log(a); ...
- javaScript变量提升以及函数提升
变量的声明赋值 var a = 1; 上面的代码先声明变量 a,然后在变量 a 与数值 1 之间建立引用关系,称为将数值 1 "赋值"给变量 a.以后,引用变量名 a 就会得到数值 ...
- 关于JavaScript的词法作用域及变量提升的个人理解
关于JavaScript的作用域,最近听到一个名词:"词法作用域":以前没有听说过(读书少),记录一下对此的理解,加深印象. 词法作用域:在JavaScript中,一个函数的作用域 ...
最新文章
- CVPR2021|Anchor-free新玩法,一个head统一目标检测,实例分割,姿态估计三种任务...
- 搭配飞行员 dinic
- 环路的产生及RIP防环机制
- TypeScript 之泛型
- Oracle中怎么设置一列的列宽,oracle - 所有列的Oracle列宽 - 堆栈内存溢出
- python3.x执行post请求时报错“POST data should be bytes or an iterable of bytes...”的解决方法...
- java中清空文件夹_java 删除文件夹中的所有内容而不删除文件夹本身的实例
- 这家自动驾驶公司,或将引领半封闭物流搬运领域的变革
- netbeans java桌面应用程序_java – 使用Netbean的桌面应用程序的状态栏
- 常用APP签名存档以及获取签名的几种方式介绍
- 备战2022软考网络管理员(1)介绍与开篇
- 大数据时代的国际贸易理论新发展
- 纯html游戏ios打包,白鹭html5游戏打包成ipa文件工具
- Qt模仿360系统托盘
- vscode汇编环境配置
- XOR Guessing
- 离散型特征编码方式:one-hot与哑变量
- 收藏的软件测试学习资源
- 关于QPS高并发,你了解多少?
- 0672-5.16.1-CDSW中Run Experiments异常分析
热门文章
- php手机省电,手机耗电量越来越多,这个开关一定要关掉!用电量才不会愈来愈高...
- layer 弹出层全屏
- 24,、135条综合布线系统专业术语,弱电人必备的知识
- 【SQL数据库设计】数据库设计【小型数据库】
- 微信小程序运营系列(二)——深入了解商户
- Java的四大修饰符
- 《PANet:Path Aggregation Network for Instance Segmentation》论文笔记
- 下一代数据存储OneStorage闪亮登场,华为打造全场景智能的基石
- VR广告飞入寻常百姓家?No,它现在还是海市蜃楼
- 「网络IO套路」当时就靠它追到女友