详解JavaScript作用域、作用域链和闭包的用法


Posted in Javascript onSeptember 03, 2020

1. 作用域

作用域是指可访问的变量和函数的集合。

作用域可分为全局作用域和局部作用域。

1.1 全局作用域

全局作用域是指最外层函数外面定义的变量和函数的集合。

换言之,这些最外层函数外面定义的变量和函数在任何地方都能访问。

举个例子:

// 最外层定义变量
var a = 1;

console.log(a); // 最外层可以访问

function fnOne() { // 最外层函数
  
  console.log(a); // 函数内可以访问
  
  function fnTwo() { // 子函数
    console.log(a); // 子函数内也可以访问
  }
}



// 说明
在最外面定义一个变量,不仅在最外面可以访问,
在函数内也能访问,在函数的子函数内也能访问。

1.2 局部作用域

局部作用域是指在函数内部定义的变量和函数的集合。

换言之,这些在函数内部定义的变量和函数,在函数外面是无法访问的,只能在函数内部(包括函数的子孙函数)访问。

举个例子:

function fnThree() {
  // 在函数内定义变量
  var b = 2;
  
  console.log(b); // 函数内部可以访问
  
  function fnFour() {
    console.log(b); // 子函数内也能访问
  }
}
// 函数外不能访问
//console.log(b); 


// 说明
在函数 fnThree 中定义一个变量 b ,在函数内可以访问,
在子函数 fnFour 中也能访问,但在 函数 fnThree 外是不能访问的。

2. 作用域链

从上面的两个例子可以看出,最里层的子函数不仅可以访问最外层函数内的变量,还能访问最外层函数外的全局变量。

这是因为,在创建最外层函数的时候,会把全局作用域拿过来,然后在创建子函数时候,又会把最外层的作用域(包括全局作用域)拿过来,就这样一环扣一环,就形成了作用域链。

所以,作用域链是指内层函数拥有外层函数到最外层(最外层函数外,全局)的所有作用域列表。

3. 闭包

闭包就是能够读取其他函数内部变量的函数。(——百度百科)

从上面的第二个例子可知,函数外是不能访问函数内部定义的局部变量,但是闭包提供了可能。

举个例子:

function User() {
	// 定义私有变量
	var userName = "default";
	
	// 提供 setUserName() 方法
	function setUserName(uName) {
		userName = uName;
	}
	
	// 提供 getUserName() 方法
	function getUserName() {
		return userName;
	}
	
	// 将方法对外开放
	return {
		set: setUserName,
		get: getUserName
	}
}

var user1 = User();
user1.set('tom');
console.log(user1.get());
var user2 = User();
user2.set('jack');
console.log(user2.get());

// 说明
User 函数内部定义变量 uesrName ,
并在内部定义两个子函数操作 userName,
最后将两个子函数返回(一个可直接放回,多个可放到对象中返回。)。

这样,在函数外面可以调用子函数访问函数内部的变量,
这两个子函数便实现了闭包的功能。

以上就是详解JavaScript作用域、作用域链和闭包的用法的详细内容,更多关于JavaScript作用域、作用域链和闭包的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
jQuery ui1.7 dialog只能弹出一次问题
Aug 27 Javascript
fireworks菜单生成器mm_menu.js在 IE 7.0 显示问题的解决方法
Oct 20 Javascript
导航跟随滚动条置顶移动示例代码
Sep 11 Javascript
js左右弹性滚动对联广告代码分享
Feb 19 Javascript
JavaScript AJAX之惰性载入函数
Aug 27 Javascript
JavaScript中各种引用类型的常用操作方法小结
May 05 Javascript
js实现音频控制进度条功能
Apr 01 Javascript
原生JS实现逼真的图片3D旋转效果详解
Feb 16 Javascript
jQuery事件blur()方法的使用实例讲解
Mar 30 jQuery
Vue CLI3中使用compass normalize的方法
May 30 Javascript
vue 实现移动端键盘搜索事件监听
Nov 06 Javascript
微信小程序中使用 async/await的方法实例分析
May 06 Javascript
JS变量提升及函数提升实例解析
Sep 03 #Javascript
Vue自定义组件双向绑定实现原理及方法详解
Sep 03 #Javascript
Vue js with语句原理及用法解析
Sep 03 #Javascript
Vue通过provide inject实现组件通信
Sep 03 #Javascript
Vue组件通信$attrs、$listeners实现原理解析
Sep 03 #Javascript
Vue父组件监听子组件生命周期
Sep 03 #Javascript
JavaScript 几种循环方式以及模块化的总结
Sep 03 #Javascript
You might like
sony ICF-2010 拆解与改装
2021/03/02 无线电
PHP5 操作MySQL数据库基础代码
2009/09/29 PHP
php操作redis缓存方法分享
2015/06/03 PHP
编写PHP脚本过滤用户上传的图片
2015/07/03 PHP
php生成固定长度纯数字编码的方法
2015/07/09 PHP
php-msf源码详解
2017/12/25 PHP
php成功操作redis cluster集群的实例教程
2019/01/13 PHP
JS的replace方法介绍
2012/10/20 Javascript
JQuery中使用Ajax赋值给全局变量失败异常的解决方法
2014/08/18 Javascript
jQuery DOM插入节点操作指南
2015/03/03 Javascript
JavaScript中的关联数组问题
2015/03/04 Javascript
JS模拟按钮点击功能的方法
2015/12/22 Javascript
jQuery formValidator表单验证
2016/01/07 Javascript
详解Angular的双向数据绑定(MV-VM)
2016/12/26 Javascript
基于Nodejs利用socket.io实现多人聊天室
2017/02/22 NodeJs
JavaScript基本类型值-Undefined、Null、Boolean
2017/02/23 Javascript
JavaScript正则表达式简单实用实例
2017/06/23 Javascript
详解Angular-cli生成组件修改css成less或sass的实例
2017/07/27 Javascript
小程序云开发实现数据库异步操作同步化
2019/05/18 Javascript
vue项目启动出现cannot GET /服务错误的解决方法
2020/04/26 Javascript
Vue Elenent实现表格相同数据列合并
2020/11/30 Vue.js
Python中装饰器兼容加括号和不加括号的写法详解
2017/07/05 Python
浅谈python之新式类
2018/08/12 Python
pycharm 批量修改变量名称的方法
2019/08/01 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
使用 Python 写一个简易的抽奖程序
2019/12/08 Python
如何通过Django使用本地css/js文件
2020/01/20 Python
python中子类与父类的关系基础知识点
2021/02/02 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
HTML5高仿微信聊天、微信聊天表情|对话框|编辑器功能
2018/04/23 HTML / CSS
欧克利英国官网:Oakley英国
2019/08/24 全球购物
汽车专业求职信
2014/06/05 职场文书
班风口号
2014/06/18 职场文书
幼儿园植树节活动总结
2014/07/04 职场文书
2015年办公室人员工作总结
2015/05/15 职场文书
SQL Server 忘记密码以及重新添加新账号
2022/04/26 SQL Server