JavaScript一看就懂(1)作用域
什么是作用域?
作用域规定变量在什么地方可用。
函数级作用域
1.函数外声明的变量为全局变量,函数内可以直接访问全局变量:
var global_var = 10; //全局变量
function a(){
alert(global_var); //全局变量在函数内可访问
}
a(); //10
2.JavaScript变量的作用域是函数级的,只有函数可以产生新的作用域,而非块级:
function a(){ //函数
if(true){ //块
var x = 1;
}
if(false){
var y = 2;
}
alert(x); //1
alert(y); //undefined
}
a();
变量x虽然在块语句(if)中声明并赋值,但它的作用域是函数a,所以在函数a的任何位置它都可访问。
有意思的是y变量的声明和赋值虽然在false块语句里,却仍然打印出undefined而不是报错,因为JavaScript会把所有变量声明提前到函数开头,称为变量提升:
function a(){
alert(x);
var x = 1;
alert(x);
}
a(); //undefined 1
//以上代码经过JavaScript变量提升后实际上是这个样子的:
function a(){
var x;
alert(x);
x = 1;
alert(x);
}
需要注意的是,在函数内声明变量一定要使用var,否则是声明了一个全局变量:
function test(){
a = 1;
}
test();
alert(a); //1
3.嵌套函数可以访问外围函数的变量
function a(){
var x = 1;
function b(){
alert(x);
var y = 2;
function c(){
alert(x);
alert(y);
}
c();
}
b();
}
a(); // 1 1 2
需要注意的是,嵌套函数里如果有同名变量,那么访问到的是嵌套函数里的变量
function a(){
var x = 1;
function b(){
var x = 2;
alert(x);
}
b();
alert(x);
}
a(); //2 1
如何做到块级作用域
通过上面的例子我们了解到JavaScript变量作用域是函数级的,但有时候我们想用临时变量怎么办呢?
通过IIFE(立即执行函数表达式)来实现:
function a(){
if(true){
(function(){ //IIFE开始
var x = 1;
alert(x); //1
}()); //IIFE结束
//alert(x); //这儿访问不到
}
//alert(x); //这儿访问不到
}
a();
这样做的好处是不会造成变量污染,用完就没了,大家商量好,过了今晚就不再联系。
作用域链
每当JavaScript解释器进入一个函数,它都会看一下附近有哪些局部变量,把它们保存到该函数的variables对象中,并创建一个scope属性来指向外部的variables对象
1. var x=1;
2. function a() {
3. var y = 2;
4. function b() {
5. var z = 3;
6. alert(x+y+z);
7. }
8. b();
9. }
10. a();
结合上面的代码,看看JavaScript引擎是如何处理作用域的:
JavaScript把所有全局对象(变量x和函数a)放到global variables对象中
global variables: x, a()
发现a是个函数,它需要一个scope属性来指向外部的variables(全局),同时把变量保存起来
a.scope -> global variables
a.variables: y, b()
来到第4行,发现b是个函数,它需要一个scope属性来指向它所在的作用域(a)
b.scope -> a.variables
b.variables: z
查找变量的时候,先看看variables对象有没有,没有就根据scope找上一级的variables,就这样一层一层往上找,直到找到为止。
参考资料
- JavaScript for PHP Developers
- 深入理解JavaScript
- You Don't Know JS
JavaScript一看就懂(1)作用域的更多相关文章
- JavaScript一看就懂(2)闭包
认识闭包之前需要先了解作用域,如果你对作用域还没有足够了解,请移步JavaScript一看就懂(1)作用域 什么是闭包? 我们可以先简单认为:一个函数a定义在另一个函数b里面,这个函数a就是闭包: f ...
- JavaScript一看就懂(3)数组
定义数组 var a = [1, 2, 3]; typeof a; //"object", 数组是对象 a.length; //数组长度 相关操作 a[0]; //下标访问 a.p ...
- 每个JavaScript工程师都应懂的33个概念
摘要: 基础很重要啊! 原文:33 concepts every JavaScript developer should know 译文:每个 JavaScript 工程师都应懂的33个概念 作者:s ...
- 每个 JavaScript 工程师都应懂的33个概念
简介 这个项目是为了帮助开发者掌握 JavaScript 概念而创立的.它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南. 本篇文章是参照 @leonardomso 创立,英文版项 ...
- 一看就懂的ReactJs入门教程(精华版)
一看就懂的ReactJs入门教程(精华版) 现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和 ...
- 《JavaScript 闯关记》之作用域和闭包
作用域和闭包是 JavaScript 最重要的概念之一,想要进一步学习 JavaScript,就必须理解 JavaScript 作用域和闭包的工作原理. 作用域 任何程序设计语言都有作用域的概念,简单 ...
- 《你必须知道的javascript(上)》- 1.作用域和闭包
1 作用域是什么 1.1 编译原理 分词/词法分析(Tokenizing/Lexing) 将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token). 解析/语 ...
- 一看就懂的Android APP开发入门教程
一看就懂的Android APP开发入门教程 作者: 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤 ...
- mysql取出现在的时间戳和时间时间戳转成人类看得懂的时间
mysql取出现在的时间戳和时间时间戳转成人类看得懂的时间,我们在mysql里面他封装了一个内置的时间戳转化的函数,比如我们现在的时间戳是:1458536709 ,"%Y-%m-%d&quo ...
随机推荐
- [译]Serilog Tutorial
在过去的几年中,结构化日志已经大受欢迎.而Serilog是 .NET 中最著名的结构化日志类库 ,我们提供了这份的精简指南来帮助你快速了解并运用它. 0. 内容 设定目标 认识Serilog 事件和级 ...
- vue.js 安装过程(转载)
一.简介 Vue.js 是什么 Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计.Vue 的核 ...
- Sping Boot入门到实战之入门篇(二):第一个Spring Boot应用
该篇为Spring Boot入门到实战系列入门篇的第二篇.介绍创建Spring Boot应用的几种方法. Spring Boot应用可以通过如下三种方法创建: 通过 https://start.spr ...
- xBIM WeXplorer 设置模型颜色
目录 基础 xBIM WeXplorer 简要介绍 xBIM WeXplorer xViewer 基本应用 xBIM WeXplorer xViewer 浏览器检查 xBIM WeXplorer xV ...
- CNN 卷积层输入Map大小计算
对于输出的size计算: out_height=((input_height - filter_height + padding_top+padding_bottom)/stride_height ) ...
- nyoj1204 魔法少女 线性DP
d[i][0]表示到达第i层,且在第i层没有使用魔法的最少时间 d[i][1]表示到达第i层,且在第i层使用魔法通过一层 d[i][2]表示到达第i层,且在第i层使用魔法通过两层 状态转移方程: d[ ...
- JS-随机生成的密码
randPassword(size) =>{ //数组 let seed = new Array('A','B','C','D','E','F','G','H','I','J','K','L', ...
- 我的Java设计模式-原型模式
"不好意思,我是卧底!哇哈哈哈~"额......自从写了上一篇的观察者模式,就一直沉浸在这个角色当中,无法自拨.昨晚在看<使徒行者2>,有一集说到啊炮仗哥印钞票,我去, ...
- javascript 获取滚动条距离顶部的位置(兼容所有的)。
function getScrollTop() { var scrollPos; if (window.pageYOffset) { scrollPos = window.pageYOffset; } ...
- 【php】DIRECTORY_SEPARATOR的作用
DIRECTORY_SEPARATOR是php的内部常量,用于显示系统分隔符的命令,不需要任何定义与包含即可直接使用. 在windows下路径分隔符是/(当然/在部分系统上也是可以正常运行的),在li ...