javascript --- 堆栈内存与闭包的作用

你可能会用到的

  • 堆内存: 存储引用类型值所在的空间
  • 栈内存: 存储基本类型值和存储代码所在空间
  • 函数上下文: 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的值并未改变.这引出了闭包的第二个作用,保护全局变量.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/250321.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python_sting字符串的方法及注释

string类型是python内置的类型&#xff0c;无需安装 方法/属性说明 capitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 center(width) 将字符串居中&#xff0c;并使用空格填充至长度width的新字符串 count(sub[,start[,end]]) …

作业3

import turtle turtle.bgcolor(red) turtle.color(yellow)turtle.fillcolor(yellow) turtle.begin_fill() for i in range(5):turtle.forward(100)turtle.right(144) turtle.end_fill() turtle.done()转载于:https://www.cnblogs.com/zhangkef97/p/9016608.html

javascript --- [小练习]变量提升、优先级综合

求下列函数输出结果 function Foo() {getName function() {console.log(1)}return this } Foo.getName function() {console.log(2) } Foo.prototype.getName function() {console.log(3) } var getName function() {console.log(4) }function getName() {console.log(5) …

Confluence 6 自定义 Decorator 模板的宏和针对高级用户

宏 页面的某些部分使用的是 Velocity 宏进行创建的&#xff0c;包括导航栏。有关宏的创建&#xff0c;你可以参考页面 Working With Decorator Macros 页面中的内容。 针对高级用户 velocity 目录是 Confluence 首先进行模板搜索的查找路径。你可以对 Confluence 的 velocity …

Matlab之rand(), randn(), randi()函数的使用方法

1. rand()函数用于生成取值在&#xff08;0~1&#xff09;之间均匀分布的伪随机数。rand(n)&#xff1a;生成n*n的0~1之间的满足均匀分布的伪随机矩阵&#xff1b;rand(m,n)&#xff1a;生成m*n的伪随机数&#xff1b;rand(m,n,double)&#xff1a;生成m*n的双精度伪随机数&am…

javascript --- [有趣的条件]双等号的隐式调用和数据劫持

1 双等号的隐式调用和数据劫持 求下面条件,在a为什么样时,等号成立 if(a 1 && a 2 && a 3){console.log(等号成立) }1.1 双等号的隐式转换 首先得了解双等号的隐式转换规则 等式备注对象 字符串隐式调用 toString方法将对象转换成字符串null undeifne…

分组查询

1、简单分组查询 语法形式&#xff1a; select function() from table_name where condition group by field; 进行分组查询时&#xff0c;分组所依据的字段上的值一定要有重复值&#xff0c;否则分组没有任何意义。 2、实现统计功能分组查询 关键字group by单独使用时&#xf…

深入探讨多模态模型和计算机视觉

近年来&#xff0c;机器学习领域在从图像识别到自然语言处理的不同问题类型上取得了显着进展。然而&#xff0c;这些模型中的大多数都对来自单一模态的数据进行操作&#xff0c;例如图像、文本或语音。相比之下&#xff0c;现实世界的数据通常来自多种模态&#xff0c;例如图像…

移动硬盘函数不正确要如何寻回资料

移动磁盘打不开函数不正确&#xff0c;是因为这个I盘的文件系统内部结构损坏导致的。要恢复里面的数据就必须要注意&#xff0c;这个盘不能格式化&#xff0c;否则数据会进一步损坏。具体的恢复方法看正文 工具/软件&#xff1a;AuroraDataRecovery 步骤1&#xff1a;先百度搜索…

vue --- [全家桶]vue-router

1. Vue - router Vue Router是 Vue.js 官方的路由管理器它和Vue.js的核心深度集成,可以非常方便的用于SPA应用程序的开发 Vue Router包含的功能有: 支持HTML5历史模式或hash模式支持嵌套路由支持路由参数支持编程式路由支持命名路由 <div id"app"><rout…

HashMap的四种访问方式

第一种&#xff1a;通过Map.entrySet使用iterator遍历key和value 1 public void visit_1(HashMap<String,Integer> hm){ 2 Iterator<Map.Entry<String,Integer>> it hm.entrySet().iterator(); 3 while(it.hasNext()){ 4 Map.Entry<String ,Integer> …

16.unix网络编程一卷 unp.h

unix网络编程 --ubuntu下建立编译环境 1.安装编译器&#xff0c;安装build-essential sudo apt-get install build-essential 2.下载本书的头文件 下载unp13e&#xff1a; http://pix.cs.olemiss.edu/csci561/prg561.1.html 3.进入unp13e 查看readme&#xff0c;照下列提示操作…

webpack --- [读书笔记] webpack中常用的一些配置项

1. Webpack 当前Web开发面临的困境 文件依赖关系错综复杂静态资源请求效率低模块化支持不友好浏览器对高级JavaScript特性兼容程度低 1.1 webpack概述 webpack是一个流行的前端项目构建工具,可以解决当前web开发中所面临的困境. webpack提供了友好的模块化支持,以及代码压…

spring中bean的作用域属性single与prototype的区别

https://blog.csdn.net/linwei_1029/article/details/18408363 转载于:https://www.cnblogs.com/stanljj/p/9907444.html

windows程序设计.第一个windos程序

Windows程序设计&#xff08;第5版&#xff09; windows程序需要调用API。 第一个Windows程序 1 /*HelloMsg.c -- Displays "Hello World!" in a message box*/ 2 #include <Windows.h> 3 4 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE…

java接口练习2

1、编写2个接口&#xff1a;InterfaceA和InterfaceB&#xff1b;在接口InterfaceA中有个方法voidprintCapitalLetter()&#xff1b;在接口InterfaceB中有个方法void printLowercaseLetter()&#xff1b;然后写一个类Print实现接口InterfaceA和InterfaceB&#xff0c;要求printC…

vue --- [全家桶] Vuex

1. Vuex 概述 1.1 组件之间共享数据的方式 父向子传值: v-bind 属性绑定子向父传值: v-on 事件绑定兄弟组件之间共享数据: EventBus$on: 接收数据的那个组件$emit: 发送数据的那个组件 1.2 Vuex是什么 Vuex: 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间…

C#/WPF程序开机自动启动

最近一个C/S项目客户要求开机自启的功能&#xff0c;网上找了一些方法&#xff0c;不顶用&#xff1b;最后自己去翻书&#xff0c;找到了这段代码&#xff0c;亲测可用&#xff0c;Wpf环境下需要改下获取程序目录的方式即可&#xff0c;Winform直接可用。 1 #regio…

github --- 多个项目的管理方式

1. 多个项目管理方式 进入项目根目录: git init 将当前的项目添加到暂存区中: git add . (注意: 最后有一个点) 将暂存区的内容放到本地仓库: git commit -m 初始化项目 登录github , 新建远程仓库 在本地添加远程仓库的源: git remote origin https://github.com/Lizhhhh/…

记录一个坑

导入项目后运行控制台打印异常,pom都已检查,没有任何问题 解决办法: 项目右击---properties---deployment assembly---add---java build path entries---maven deoendencies 保存并关闭 解决... 这个问题第一次遇到 检查了很多遍maven的依赖,明明都已经配置好了 ,仍然产生了…