你可能会用到的

  • 堆内存: 存储引用类型值所在的空间
  • 栈内存: 存储基本类型值和存储代码所在空间
  • 函数上下文: JS每一个函数在执行的时候都会创建一个执行上下文

1. 堆内存中的数字和字符串都是相等的

let a = {}, b='0', c=0;
a[b] = 'marron';
a[c] = 'Mar'
console.log(a[b]) // Mar
  • 第一行代码, a创建是一个对象,对象在JS中是引用类型,因此会创建一个堆内存来存储对象
// 堆: AAAFFF00
(此时里面是空的)
  • 此时a的值实际上是指向这个堆的地址,即A = AAAFFF00
  • 在执行 a[b] = 'marron'时,实际上会给堆内存中键为’0’赋上值 ‘marron’
// 堆: AAAFFF00
'0': 'marron'
  • 在执行a[c] = 'Mar'时,由于堆中字符串和数字默认是相等的,此时堆内存中实际的操作是:
// 堆: AAAFFF00
+ '0': 'Mar'
  • 因此最后输出的回收’Mar’

2.对象作为值在堆内存中都会隐式调用toString方法,变为字符串

let a = {},b = {n: '1'},c = {m: '2'}
a[b] = 'marron'
a[c] = 'Mar'
console.log(a[b]);      // 'Mar'
// 在堆内存中都是   { '[object object]': 'Mar' }
  • 执行a= {}时,
// 堆: AAAFFF01
  • 此时 a = AAAFFF01
  • 执行a[b] = 'marron'
  • 会先隐式调用b.toString(),然后将得到的结果存放到 堆AAAFFF01中
// 堆: AAAFFF01
'[Object Object]': 'marron'
  • 执行a[c] = 'Mar',同理
// 堆: AAAFFF01
'[Object Object]': 'Mar'
  • 因此,最后会输出 ‘Mar’

3. 闭包问题

var test = (function(i){return function(){alert(i *= 2)}
})(2)
test(5)

3.1 需要了解的

  1. 函数上下文: JS中每一个函数在执行的时候都会创建一个执行上下文
  2. 堆内存: JS中每一个引用类型的操作,都对应一个堆内存

3.2 解析

  • var test = (function(i){...})(2),等号右边是一个自执行函数.执行函数的时候会创建一个执行上下文
// 自执行函数的执行上下文
i = 2;
return function(){}
  • 遇到return function(){}中的function是一个引用类型,故会创建一个堆内存
// 堆: AAAFFF00
"alert(i *=2)"
...
  • 然后将堆内存的地址返回,此时堆内存的上一级作用域是自执行函数的执行上下文
// 自执行函数的 执行上下文
i = 2;
return AAAFFF00
  • 此时test的值是堆的内存地址: test = AAAFFF00
  • 之后遇到了 test(5),函数执行会创建一个执行上下文
// test(5)的 执行上下文
-> 堆: AAAFFF11
  • 然后顺着地址去找到堆AAAFFF11,找到堆AAAFFF11之后,遇到函数代码字符串. alert( i *= 2),
// test(5)的 执行上下文
"alert( i*= 2)"
  • 由于当前堆中没用i的值,会顺着作用域链,往上级作用域寻找,找到了 自执行函数的上下文.然后回弹出字符串 “4”,同时堆内存中i的值被改成了4

  • 完毕之后,由于test(5)的执行上下文中没用变量被引用,会根据JS的垃圾回收机制,进行销毁.

  • 自执行函数的 执行上下文中的变量i被堆AAAFFF11引用,会一直存在,因此形成了闭包.

4. 闭包小练手

var a = 0,b = 0;
function A(a){A = function(b){alert(a + b++);};alert(a++)
}
A(1);
A(2);
  • 首先有个全局作用域
// global
a = 0;
b = 0;
A = 堆: FFFAAA00
ctx:A(1)
ctx:A(2)
  • 执行到A(1)
// ctx: A(1)
a(局部) = 1
A(全局) = 堆: FFFAAA01
alert(a++)     // 会弹出'1',此时局部a = 2
// 由于a被堆: FFFAAA01 引用,因此结束时, ctx: A(1)不会被清除,形成了闭包哟.
  • A(1)执行完毕,此时全局作用域
// global
a = 0;
b = 0;
A = 堆: FFFAAA01
ctx: A(2)  <-- 执行到这一行
  • A(2)开始执行
// ctx: A(2) 传入参数由b接收
a(ctx(A(1))) = 2;
b(局部) = 2;
alert(a + b++); // 弹出'4', 然后局部b = 3
// 完毕后,作用域销毁
// 注: A此时执行的是堆: AAAFFF01,堆并未消失
  • 综上所述,会弹出’1’,‘4’

说明: 上面执行了2次A函数,且分别用到了a , b变量…但是在对a,b变量操作完成后.全局变量的a和b的值并未改变.这引出了闭包的第二个作用,保护全局变量.

javascript --- 堆栈内存与闭包的作用相关推荐

  1. 前端面试题讲解(THIS、构造函数、面向对象、堆栈内存以及闭包)

    视频地址:https://www.bilibili.com/video/av24383268/?p=13 02. JS中的严格模式和ARG映射机制 EXP1 EXP2 映射机制 严格模式 03. 逻辑 ...

  2. 夯实基础,彻底掌握js的核心技术(三):堆栈内存及闭包详解

    数据渲染机制及堆栈内存 1. 数据值操作机制 /* * 1. 先声明一个变量a,没有赋值(默认值谁undefined) * 2. 在当前作用域中开辟一个位置存储12这个值 * 3. 让变量a和12关联 ...

  3. JavaScript的内存作用域闭包

    1. 执行上下文与作用域 执行上下文简称 " 上下文 ",变量和函数的上下文决定了它们可以访问哪些数据.以及它们的行为.每个上下文都有一个变量对象 VO(variable obje ...

  4. 【金三银四】 一文弄懂 js 数据类型、堆栈内存、作用域(链)、闭包知识拓展 (一)

    引言 对答如流系列篇,关于基本数据类型.堆栈内存.作用域作用域链.闭包 大家好,这里是lionLoveVue,基础知识决定了编程思维,学如逆水行舟,不进则退.金三银四,为了面试也还在慢慢积累知识,Gi ...

  5. javascript基础系列:堆栈内存(stackamp;heap)(二)

    忙了一段时间,很容易忘记更新博客文章,拖延症很严重,今天晚上趁着有时间,继续系统温习,希望对大家有所帮助.本文章仅代表前端岚枫的个人观点,有不正确还望指出. 浏览器运行机制及基本类型与引用类型的区别 ...

  6. javascript深入理解js闭包[转]

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  7. javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  8. 面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)

    文章目录 对JS闭包的理解及常见应用场景(闭包的作用) 1.变量作用域 2.如何从外部读取函数内部的变量? 3.闭包概念 4.闭包用途 5.闭包的理解 6.闭包应用场景 setTimeout传参 回调 ...

  9. [javascript] 深入理解js闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

最新文章

  1. HiCar基本功能介绍
  2. 张晓帆:一个决定将47万奖金全部投入科研的博士生
  3. 利用STM32 的串口来发送和接收数据实验
  4. python五十一:动态导入模块,通过字符串导入模块
  5. 中國批准英特爾在東北投建晶片廠
  6. 开源 | 如何实现一个iOS AOP框架?
  7. 优化大数据分析的五个小技巧
  8. Asp.net web api 知多少
  9. c语言n天前是星期几,新手做的日历表及查找日期是星期几
  10. learning opencv3: 一:overview 打开自己的视频文件加上暂停快进按钮
  11. 持续改进----白狼族的故事(完结)
  12. rar压缩文件密码破解
  13. matlab程序阻尼牛顿法,matlab阻尼牛顿法
  14. 关于jmstudio 调用本地摄像头的问题
  15. c语言.jpg图片转成数组_AWTK——基于C语言开发的GUI框架,功能强大,支持跨平台同步开发...
  16. Android 版本简介
  17. 手把手教你开发IOT设备
  18. 第一代计算机硬件逻辑主要采用电子管,云南省计算机一级考试题库4
  19. C语言汇编查看笔记(一)
  20. Lomboz的安装与下载(转)

热门文章

  1. mysql 中文字段名_MySQL全文索引怎么做?| 教程分享
  2. js封装函数_JavaScript基础-如何封装函数来改变元素的位置
  3. mysql第四项_mysql数据库的基本介绍与操作(第四篇-mysql索引篇)
  4. GPU Gems1 - 9 有效的阴影体渲染
  5. ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)...
  6. [webrtc] rtcp模块中rtt时间计算
  7. Android开发学习---使用Intelij idea 13.1 进行android 开发
  8. 考研数学:【以错补错】 降低做题出错率
  9. GooglePR说明
  10. Node — 第九天 (ES6降级 and 发布属于自己的[第三方模块]包)