深入理解JavaScript的函数作用域
什么是作用域 ?
作用域:一个变量可以生效的范围。 变量不是在所有地方都可以使用的,而这个变量的使用范围就是我们要说的作用域。
注意:在JavaScript中,划分作用域也是用大括号划分的, 但是在 JS 之中能够有效限定作用域的大括号只有函数大括号!
有哪些作用域 ?
- 全局作用域(不再任何函数内)
学习使用作用域,以下内容是所需要了解的:
- 全局作用域是最大的作用域
- 在全局作用域中定义的变量可以在任何地方使用
- 页面打开的时候,浏览器会自动给我们生成一个全局作用域 window
- 这个全局作用域会一直存在,直到页面关闭才会销毁
请看下面示例代码:
var a = 10;
console.log(a); // 输出结果: 10
function foo(){
console.log(a); // 输出结果: 10
}
foo()
当变量 a 声明时,没有被函数大括号包裹, 那么这个变量我们称之为 全局变量
这个全局变量在任何地方都可以访问。
- 局部作用域(在函数内部)
同样的,以下内容也是所需要了解的:
- 局部作用域就是在全局作用域下面开辟出来的一个相对小一些的作用域
- 在局部作用域中定义的变量只能在这个局部作用域内部使用
- 在 JS 中只有函数能生成一个局部作用域,别的都不行
- 每一个函数,都是一个局部作用域
请看下面示例代码:
function foo(){
var a = 10; //在大括号之中声明的变量只能在这个大括号之中使用;
console.log(a); // 输出结果: 10
}
foo();
console.log(a); // 报错 => ReferenceError: a is not defined
通过上面示例代码可以看出:
在函数大括号之中声明的变量,这种变量我们称之为 局部变量 !
局部变量只能在声明它的作用域之中使用;
我们见惯了常规情况,现在看一个特殊情况:
声明变量时不使用 var 关键字声明:
注意!这是一个不规范的声明方式!不要使用!不要使用!不用使用!
使用之后导致的结果就是:一个局部变量的声明,在全局中也可以被访问了!( 这样的声明叫做 伪全局变量 )
请看下面示例代码:
function foo(){
a = 10; // 此时声明变量 a 没有使用var关键字声明
console.log(a); //
}
foo();
console.log(a); // 输出 10,不报错了;
看完上面的代码示例,你是不是觉得这不挺好的嘛,变量 a 可以随便使用,都不用报错了,为什么不让使用??
呵呵,别高兴太早,继续往下看,你的这个想法很危险的!
当把局部变量变成伪全局变量:
你会发现:
- 生命周期变长,造成一定的负面影响;
- 占据了全局命名空间,造成不可预知的错误

是不是脑子里突然蹦出了好多问题:生命周期是什么鬼?命名空间又是什么鬼??
好吧,上面这个内容我说早了,那么接着往下看:
全局变量和局部变量的区别:
在这里就来聊一下上面的生命周期和命名空间吧!
生命周期(这个变量在内存之中存活的时间)
就是你啥时候可以访问!
- 全局变量:生命周期是和程序同步的, 程序不关闭,变量就一直存在;
导致的结果就是会让程序变得更重! 如果可能,还是少设计一点全局变量吧!对大家都好
- 局部变量:生命周期是和函数执行同步的,函数执行结束变量就被删除了;
现在知道啥是生命周期了吧,全局变量多了,可能真的会影响到我们程序的运行效率,上面说的伪全局变量就是这个道理。
我们看完了生命周期,再来一起看一下命名空间吧!
命名空间(变量名命名的唯一性)
- 全局变量:命名空间是唯一的,一个页面只有一个
我们先来举一个小例子,话不多说上代码:
var count = 10;
function foo(){
// 我的代码 : 我的私人领域;
// 程序的懒惰原则:函数的大括号之中如果已经有了查找结果,那么就不会继续再查找了;
// 就近原则;
var count = 0;
console.log(count); // 运行结果:0
}
foo();
console.log(count); // 运行结果:10
为了解决全局之中的命名空间是唯一的这个问题,我们可以把这个变量放在局部,那么就不会占用全局的命名空间了。
- 局部变量:命名空间一个作用域一个
可以用匿名函数来解决命名空间的问题
最后一个问题:我现在要写一大坨代码,和别人的代码要配合 。 这个时候咋写呢???
我可以把代码写在一个没有名字的函数之中! 什么?这样写直接报错 ?
JS为啥阻止他 ? 如果我立即调用呢!来一个瞒天过海如何?
让匿名函数经历一次运算: 如果函数发生了特定的运算, 那么这个函数就会被当做一个地址;
// 让匿名函数经历一次运算: 如果函数发生了特定的运算,那么这个函数就会被当做一个地址;
// var res = 1 + function(){}
// console.log(res); //运行结果:1function(){} // 利用这个机制使用匿名函数立即调用 :
// +function(){
// console.log("hello world")
// }(); // 函数经过运算变成了地址,被后面的调用运算符调用了;
// !function(){
// console.log("hello world")
// }(); // 一种普遍的写法 : // (function(){
// console.log("hello world1");
// })()
// 可能存在的bug;
// (function(){
// console.log("hello world1");
// })();
// //两个匿名函数同时是使用一定要加上分号
// (function(){
// console.log("hello world2");
// })();
// 建议写法;
;(function(){
console.log("hello world1");
})();
最后来个总结吧!
1、全局不能访问局部
2、局部可以拿到全局
喜欢的朋友可以点点关注,点点赞,欢迎评论区留言互动。
深入理解JavaScript的函数作用域的更多相关文章
- 深入理解 JavaScript 变量的作用域和作用域链
一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...
- javascript篇-----函数作用域,函数作用域链和声明提前
在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...
- 理解javascript 回调函数
##回调函数定义 百度百科:回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不 ...
- 深入理解JavaScript中的作用域和上下文
介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...
- JavaScript之函数作用域
有过类似C语言编程经验的同学应该都知道“块级作用域(block scope)”:花括号内的每一段代码都具有各自的作用域,而且在声明它们的代码段之外是不可见的.而在JavaScript中是没有块级作用域 ...
- 谈谈javascript的函数作用域
在一些类似c语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明他们的代码段之外是不可见的,我们称为块级作用域(block scope),而javascript中没有块级作用域.取 ...
- 理解 JavaScript 回调函数并使用
JavaScript中,函数是一等(first-class)对象:也就是说,函数是 Object 类型并且可以像其他一等对象(String,Array,Number等)一样使用.它们可以"保 ...
- 理解JavaScript中的作用域和上下文
JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...
- 深入理解JavaScript中的作用域、作用域链和闭包
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qappleh/article/detai ...
随机推荐
- linuxmint截图
利用import命令截图,并设置快捷键 shift + PrtScrSysRq: 选中区域截图. 设置快捷键的时候,提示: Ctrl + PrtScrSysRq: 复制截图到剪切板 PrtScrSys ...
- Django框架篇
Django框架 1.HTTP超文本传输协议 8中请求方法 GET , POST ,HEAD ,PUT ,DELETE , TRACE ,OPTIONS ,CONNCT 状态码 1xx ;服务器收到请 ...
- Flink(三) —— 运行架构
Flink运行时组件 JobManager 作业管理器 TaskManager 任务管理器 ResourceManager 资源管理器 Dispatcher 分发器 任务提交流程 任务调度原理 Job ...
- 36)PHP,搜寻数据库信息在html中显示(晋级1)
首先是数据库的样子展示: 然后就是我的PHP主文件了: <?php class db { public $host="localhost" ;//这个是主机的地址 publi ...
- 在windows系统下安装使用msf
前沿 msf基本是我在kali里最经使用的工具了 因为今天碰到一些关于VmWare的事情没有解决 windows在前一段时间更新,要求我卸载vmware虚拟机,否则就无法更新. 卸载之后再装回来就无法 ...
- 基于 maven 的ssm 框架搭建
1.新建一个 maven 工程, war 包 2.引入 pom 文件(springmvc+spring+mybatis) 3.引入配置文件 4.引入页面,编写 contorller 层测试 5.编写查 ...
- Office 365管理员添加自定义域名
添加自定义域,以便Office 365允许更短.更熟悉的的电子邮件或用户ID用于服务 一.Office 365小型企业版添加自定义域名 1.使用Office 365管理员账户登陆到由世纪互联运营的Of ...
- [LC] 124. Binary Tree Maximum Path Sum
Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any ...
- CentOS换yum源和epel源为国内源
CentOS换源 YUM源 备份原来的repo文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bac ...
- 隐藏windows7/8“卸载或更改程序”里的软件
隐藏windows7/8“卸载或更改程序”里的软件 通过修改注册表即可隐藏电脑中已安装的软件,这个方法会造成卸载列表无法加载已安装的软件,请谨慎操作!提示:删除注册表后windows自带的卸载程序.其 ...