关于javascript:几个例子理解不同数据类型的堆栈内存处理

33次阅读

共计 2210 个字符,预计需要花费 6 分钟才能阅读完成。

如有谬误烦请斧正

js 代码的运行环境

  • 浏览器 内核(引擎)
  • node
  • webview(hybrid,嵌入到手机 app 外面,在 app 外面运行)

上面通过几个例子了解不同数据类型的堆栈内存解决

js 如何运行(示例 1)

var a = 12;
var b = a;
b = 13;
console.log(a);

浏览器可能运行 js 代码,是因为浏览器会在计算机内存中调配出一块内存,用来供代码执行,这块内存叫 栈内存 ,也叫 Stack,或者 ECStack(Execution Context Stack) 执行环境栈

为了辨别是哪个区域(全局或者函数等)下的代码执行,会产生一个 执行上下文(EC:Execution Context)。所谓执行上下文,其实是一个形象的概念,简略来了解就是代码执行区域的划分。

在全局环境下会产生 EC(G):Execution Context(golbal)全局执行上下文 ,其中 VO(G) 全局变量对象(Varibale Object)存储全局执行上下文申明的变量,而后进入栈内存执行。

申明变量的步骤

接着开始执行,先 申明变量,申明变量有三步

var [变量] = [值]

  1. 先创立值(执行等号左边)

    • 根本数据类型是间接存储在 栈内存 当中
    • 援用类型的值,都是开拓一个独自的内存空间(堆内存Heap)存储信息
  2. 申明变量 declare

    • 寄存到以后上下文的变量对象中(VO/AO)
  3. 定义(赋值)变量:让变量和值关联到一起,也就是所谓的赋值操作,也叫定义(defined)或指针指向

    • 所以var n; // 默认值是 undefined 未定义

所以 var a = 12 步骤是

  1. 在内存中开拓空间,存储 12
  2. 申明变量a
  3. 12 赋值给a

var b = a 解决是

因为右侧的 a 不是值,所以不须要第一步,不须要在栈外面开拓空间,间接进行第二步申明,而后执行第三步,关联到 12 值(指针)

b=13的解决步骤是

  1. 在内存中开拓空间,存储 13
  2. 因为 b 曾经在以后上下文的变量对象中,所以不须要第二步申明
  3. 13 赋值给b

后果:

总体执行逻辑:

js 如何运行(示例 2)

var a = {n: 12};
var b = a;
b['n'] = 13;
console.log(a.n);

当第一步创立的值是一个援用类型的值时候,值就没法间接存到栈里(没有这么大的空间)。当创立援用类型值的时候,会进行以下解决

  • 在计算机内存中调配一个独自的内存进去(堆内存 Heap)
  • 这块堆内存有一个 16 进制的地址用来寻找
  • 把对象中的键值对别离存储到堆内存当中
  • 把堆内存地址搁置到栈中,供变量调用

这就是第一步,创立值 的过程

第二步申明。第三部赋值,将 16 进制的地址 赋值给变量

var b = a;时,因为 a 为 变量,所以不须要创立值,接着申明 b,最初赋值,将栈中a 指向的地址也同样赋值给 b,让b 也指向那个16 进制地址

b['n'] = 13运行原理:

b['n'] = 13属于对象的成员拜访

  • b首先基于地址 0x000000 找到堆内存
  • 把堆内存中成员为 n 的值改为13
  • console.log(a.n)也属于成员拜访 所以输入13

程序如下

总结:根本数据类型和援用数据类型的区别?
根本类型的值间接存储在栈内存当中,间接依照值操作,援用数据类型值是开拓独自的堆内存存储信息的,将堆内存的地址存在栈当中,操作的都是援用地址

js 如何运行(示例 3)

var a = {n: 12};
var b = a;
b = {n: 13};
console.log(a.n);

当到 b = {n: 13};

新开拓一个堆内存{n: 13},将地址指向 b

GO global object 全局对象

不同于 VO,VO(G)是全局变量对象,存储以后上下文申明的变量的

GO global object 全局对象 ,是加载页面默认造成的。在浏览器中,加载页面时,在 全局上下文 中会默认定义一个叫 window 的对象,其中有 setTimeout,setInterval 等供 js 调用的属性和办法


留神辨别 VO 和 GO

JavaScript 中有一个非凡的对象,称为 全局对象(Global Object),它及其所有属性都能够在程序的任何中央拜访,即全局变量
在浏览器 JavaScript 中,通常 window 是全局对象,而 Node。js 中的全局对象是 global,所有全局变量(除了 global 自身以外)都是 global 对象的属性。
在 Node。js 咱们能够间接拜访到 global 的属性,而不须要在利用中蕴含它。
globalprocess__filename__dirname

js 如何运行(示例 4)

var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);
console.log(b);
var a = {n: 1};
var b = a;

前两行代码执行如下,不在论述:

要想了解a.x = a = {n: 2};

简略说一下运算符优先级

var a=12,b=13;

相当于

var a=12
var b=13
var a=b=13

相当于

b=13
var a=b// 或者 var a=13

失常计算都是从右到左解决的(当然第一步还是创立值)

然而不论是 a.x=b=13 还是 b=a.x=13
都要先计算 a.x 因为优先级比拟高(成员拜访的优先级为 19,仅次于 () 运算,运算符优先级)

a.x = a = {n: 2};运算步骤如下

  1. 开拓内存,假如地址为 0x000001
  2. 将地址放入栈中
  3. a.x = 地址
  4. a = 地址

所以当初 a 指向 0x000001,b指向 0x000000,即
a{n:2}b{n:1,x:{n:2}}

后果:

一个变量只能够关联一个栈中的值,然而一个栈中的值,能够被多个变量关联

正文完
 0