先上定义
- 作用域:
官方解释:一段程序代码中所用到的变量并不总是可用的,而限定这个变量的可用性的代码范围就是改变量的作用域
- 闭包:
闭包就是能够读取其他函数内部变量的函数
任何没有代码来支撑的定义和解释都是扯淡,务必静下心来看看下面的例子
作用域
举?一:
function outFun() {
var num = 1 // 内部变量 num
console.log(num) // 1
}
console.log(num) // 通过运行上面的代码 控制台 打印结果 ReferenceError: num is not defined
outFun()
上述简单的演示就可以出刊端倪,也如您所愿,之所有产生如上结果,就是因为变量 num 只存在于 count 函数内,被称之为局部变量,只有 count 内部可以访问。
举?二:
function outFun() {
var num = 1 // 变量 num 在函数 count 内部
function innerFun() {
console.log(num) // 1
// ...... 此处省略 n 多函数
}
// ...... 此处省略 n 多函数
console.log(num) // 1
console.log(innerFun())
}
outFun()
运行上述代码,你会发现,内部函数 innerFun 中也可以正常输出 num 的值,这是因为 innerFun 在外部函数 outFun 内部
举?三:
function outFun() {
var num = 1 // 变量 num 在函数 count 内部
function innerFun() {
var count = 999;
console.log(num) // 1
console.log(count) // 999
// ...... 此处省略 n 多函数
}
// ...... 此处省略 n 多函数
console.log(num) // 1
console.log(innerFun())
console.log(count) // undefined
}
outFun()
运行上述代码,你会发现,内部函数 innerFun 中也可以正常输出 num 的值,这是因为 innerFun 在外部函数 outFun 内部,但是 外部函数 outFun 无法访问 内部函数 innerFun 中的 count 变量。
以上三个简单的例子,很好的解释了最初的定义(记得巩固一下),当然每一个Function都有自己的作用域这个你得知道,不要问我为什么。
作用域链
提问
- 什么是作用域链?
- 作用域链是怎么形成的?
这里就不引用一些官方的解释了,太绕而且不易读,这里只谈谈自己的理解
- 作用域链:函数的嵌套形成不同的层级的作用域,内层函数对外层函数中变量的引用形成作用域链
也就是说,作用域链的形成以及复杂程度和函数的嵌套有关
图解作用域链:
闭包
在讲解闭包之前先讲讲个人理解的闭包的模式:外层函数的局部变量被内层函数所引用,调用外层函数返回内层函数
举例:
function a() {
var str = 'hello world'
return function b() {
console.log(str)
}
}
a() // 返回 内层函数 b, 但是根据垃圾回收机制, 函数 a 中的局部变量 str 依然被函数 b 所使用,所以不会被系统进行回收,也就会一直占用内存
关于堆栈调用请狠狠的点击这里:https://mp.youkuaiyun.com/postedit/85038675
如此就形成了一个最简单的闭包
讲完了基础的定义,再来看看实际使用场景
编写一个计算月开销的函数,不用每天就进行计算,只有在需要的时候进行求值:
var cost = (function(){
var args = [];
return function(){
if ( arguments.length === 0 ){
var money = 0;
for ( var i = 0, l = args.length; i < l; i++ ){
money += args[ i ];
}
return money;
}else{
// 传参的时候
Array.prototype.push.apply( args , arguments ); // 向数组中添加成员
}
}
})();
cost( 100 ); // 未真正求值
cost( 200 ); // 未真正求值
cost( 300 ); // 未真正求值
console.log( cost() ); // 求值并输出: 600
以上代码通过匿名函数的自调返回每部函数,内部函数始终保持对外层函数的引用
结语
以上是对作用域、作用域链、以及闭包的最简单且最直接的讲解,万变不离其中,更深入的理解和运用,需要去实践,可以参考面试题的分享 某上市公司的前端面试题
其它前端性能优化:
- 图片优化——质量与性能的博弈
- 浏览器缓存机制介绍与缓存策略剖析
- webpack 性能调优与 Gzip 原理
- 本地存储——从 Cookie 到 Web Storage、IndexDB
- CDN 的缓存与回源机制解析
- 服务端渲染的探索与实践
- 解锁浏览器背后的运行机制
- DOM 优化原理与基本实践
- Event Loop 与异步更新策略
- 回流(Reflow)与重绘(Repaint)
- Lazy-Load
- 事件的节流(throttle)与防抖(debounce
- 前端学习资料下载
- 技术体系分类
前端技术架构体系(没有链接的后续跟进):
- 调用堆栈
- 作用域闭包
- this全面解析
- 深浅拷贝的原理
- 原型prototype
- 事件机制、
- Event Loop
- Promise机制、
- async / await原理、
- 防抖/节流原理
- 模块化详解、
- es6重难点、
- 浏览器熏染原理、
- webpack配置(原理)
- 前端监控、
- 跨域和安全、
- 性能优化(参见上面性能优化相关)
- VirtualDom原理、
- Diff算法、
- 数据的双向绑定
- [TCP协议(三次握手、四次挥手)](https://blog.youkuaiyun.com/woleigequshawanyier/article/details/85223642
- DNS域名解析
其它相关
欢迎各位看官的批评和指正,共同学习和成长
希望该文章对您有帮助,你的 支持和鼓励会是我持续的动力