深入理解js数据类型与堆栈内存(上)

简介: 深入理解js数据类型与堆栈内存(上)

前言


在JavaScript中,它的内存分为三种类型:代码空间、栈空间、堆空间,其中代码空间用于存放可执行代码。


本文带大家来深入理解下栈空间与堆空间(堆内存与栈内存),欢迎各位感兴趣的开发者阅读本文。


理解数据类型


最新的 ECMAScript 标准定义了 9 种数据类型:


  • 6 种原始类型,使用 typeof 运算符检查
  • undefined:typeof instance === "undefined"
  • Boolean:typeof instance === "boolean"
  • Number:typeof instance === "number"
  • String:typeof instance === "string
  • BigInt:typeof instance === "bigint"
  • Symbol :typeof instance === "symbol"
  • null:typeof instance === "object"
  • Object:typeof instance === "object",任何构造函数对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过new关键词创建的东西。
  • Function:非数据结构,尽管 typeof 操作的结果是:typeof instance === "function"。这个结果是为 Function 的一个特殊缩写,尽管每个 Function 构造器都由 Object 构造器派生。


typeof 操作符的唯一目的就是检查数据类型,如果我们希望检查任何从 Object 派生出来的结构类型,使用 typeof 是不起作用的,因为总是会得到 "object"。检查 Object 种类的合适方式是使用 instanceof 关键字。但即使这样也存在误差。


动态类型


JavaScript 是一种弱类型或者说动态语言。我们不需要提前声明变量的类型,在程序运行过程中,类型会被自动确定。这也意味着我们可以使用同一个变量保存不同类型的数据:


var info = "字符串类型"; // string类型
info = 20; // number类型
info = true; // boolean类型


隐式转换


  • +-运算符转换


console.log("20" + 6) // "106" 字符串拼接 string + number = string
console.log("16" - 6) // 10 减法运算 string - number = number


  • 比较运算符


// ==(等于),会自动转换数据类型再比较
// ===(严格等于),不会自动转换数据类型,如果数据类型不一致,返回false;如果一致,再比较。
false == 0; // true
false === 0; // false
undefined == null; // true,(undefined是null的子集)


  • NaN(Not a Number)这个特殊的Number与所有其他值都不相等,包括它自己:


NaN === NaN; // false
isNaN(NaN);  // true (isNaN() 函数用于判断NaN)


  • 浮点数相等比较


1 / 3 === (1 - 2 / 3); // false
// 浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true


包装对象


在JavaScript中,一切皆对象Array(数组)和 Function(函数)本质上都是对象,就连三种原始类型的值 — — Number(数值)、String(字符串)、Boolean(布尔值) — — 在一定条件下,也会自动转为对象,也就是原始类型的 包装对象


一般来说,只有对象是可以对属性进行读写操作的,但是我们平常用的很多的字符串方法和属性,都是通过.操作符访问的,例如:


console.log("神奇的程序员".length);
console.log("我是大白".indexOf("白"));


如上述代码所示,在我们调用这些方法和属性时,JS内部已经隐式地帮我们帮创建了一个包装对象了,上述代码JS在运行时会处理成这样:


console.log(new String("神奇的程序员").length);
console.log(new String("我是大白").indexOf("白"));


浏览器自己隐式创建的包装对象和我们显式创建的包装对象不严格相等,我们举个例子

说明下:


var name =  "神奇的程序员";
var info = new String("神奇的程序员");
console.log(name == info);    // true
console.log(name === info);   // false


运行结果如下:


640.png

                             image-20210323224807378


类型检测


接下来我们来学习下js中几个常用的类型检测方法。


typeof运算符


typeof可以检测变量的数据类型,返回如下6种字符串numberstringbooleanobjectundefinedfunction

我们举个例子说明下:


var age = 1;
console.log(typeof age);  // number
var info = undefined;
console.log(typeof info);  // undefined
var title = null;
console.log(typeof title);  // object,(null是空对象引用/或者说指针)。
var obj = new Object();
console.log(typeof obj);  // object
var arr = [1,2,3];
console.log(typeof arr);  // object 
var fn = function(){}
console.log(typeof fn);  // function


运行结果如下:


640.png

                                  image-20210323224959529


instanceof运算符


  • instanceof,用于检测某个对象的原型链是否包含某个构造函数的 prototype 属性。
  • instanceof 适用于检测对象,它是基于原型链运作的。
  • instanceof 除了适用于任何 object 的类型检查之外,也可以用来检测内置对象,比如:ArrayRegExpObjectFunction
  • instanceof 对基本数据类型检测不起作用,主要是因为基本数据类型没有原型链。


我们举个例子来说明下:


console.log([1, 2, 3] instanceof Array); // true
console.log(/abc/ instanceof RegExp); // true
console.log({} instanceof Object); // true
console.log(function() {} instanceof Function); // true


运行结果如下:


640.png

                                     image-20210323225421217


constructor属性


构造函数属性,可确定当前对象的构造函数,我们举个例子说明下:


var o = new Object();
console.log(o.constructor == Object); // true
var arr = new Array();
console.log(arr.constructor == Array); // true


运行结果如下:


640.png

                           image-20210323225557196


hasOwnProperty属性


判断属性是否存在于当前对象实例中(而不是原型对象中),我们举个例子来说明下:


const info = { title: "书", name: "大白" };
console.log(info.hasOwnProperty("title")); // true


运行结果如下:


640.png

                              image-20210323225809992


堆栈内存空间


接下来,我们看下什么是堆、栈内存空间。


栈内存空间


见名知意,栈内存空间 就是用栈作为数据结构在内存中所申请的空间。


对栈这种数据结构不了解的开发者,请移步我的另一篇文章:数据结构:栈与队列。

我们来回顾下的特点:


  • 后进先出,最后添加进栈的元素最先出。
  • 访问栈底元素,必须拿掉它上面的元素。


我们画个图来描述下栈,如下所示:


640.png

                         image-20210323113726313


堆内存空间


同样的,见名知意,堆内存空间就是用堆作为数据结构在内存中所申请的空间。


对堆这种数据结构不了解的开发者,请移步我的另外两篇文章:数据结构:堆、实现二叉堆

通常情况下,我们所说的 数据结构指的是 二叉堆 ,我们来回顾下二叉堆的特点:


  • 它是一颗完全二叉树
  • 二叉堆不是最小堆就是最大堆


我们画个图来描述下 最大堆最小堆 ,如下所示:


640.png


                                image-20210323134717994

相关文章
|
9天前
|
存储 JavaScript 前端开发
JS 中的内存管理
【10月更文挑战第17天】了解和掌握 JavaScript 中的内存管理是非常重要的。通过合理的内存分配、及时的垃圾回收以及避免内存泄漏等措施,可以确保代码的高效运行和稳定性。同时,不断关注内存管理的最新发展动态,以便更好地应对各种挑战。在实际开发中要时刻关注内存使用情况,以提升应用的性能和质量。
17 1
|
22小时前
|
监控 JavaScript 前端开发
如何检测和解决 JavaScript 中内存泄漏问题
【10月更文挑战第25天】解决内存泄漏问题需要对代码有深入的理解和细致的排查。同时,不断优化和改进代码的结构和逻辑也是预防内存泄漏的重要措施。
9 6
|
22小时前
|
JavaScript 前端开发 Java
JavaScript 中内存泄漏的几种常见情况
【10月更文挑战第25天】实际上还有许多其他的情况可能导致内存泄漏。为了避免内存泄漏,我们需要在开发过程中注意及时清理不再需要的资源,合理使用内存,并且定期检查内存使用情况,以确保程序的性能和稳定性
8 2
|
4天前
|
存储 JavaScript 前端开发
js 中有哪几种内存泄露的情况
JavaScript 中常见的内存泄漏情况包括:1) 全局变量未被释放;2) 意外的全局变量引用;3) 被遗忘的计时器或回调函数;4) 事件监听器未被移除;5) 子元素存在时删除父元素;6) 循环引用。
|
13天前
|
存储 JavaScript 前端开发
JavaScript 数据类型详解:基本类型与引用类型的区别及其检测方法
JavaScript 数据类型分为基本数据类型和引用数据类型。基本数据类型(如 string、number 等)具有不可变性,按值访问,存储在栈内存中。引用数据类型(如 Object、Array 等)存储在堆内存中,按引用访问,值是可变的。本文深入探讨了这两种数据类型的特性、存储方式、以及检测数据类型的两种常用方法——typeof 和 instanceof,帮助开发者更好地理解 JavaScript 内存模型和类型检测机制。
30 0
JavaScript 数据类型详解:基本类型与引用类型的区别及其检测方法
|
18天前
|
缓存 监控 JavaScript
|
13天前
|
JavaScript 前端开发 算法
深入理解JavaScript的内存管理机制
【10月更文挑战第13天】深入理解JavaScript的内存管理机制
28 0
|
14天前
|
存储 JavaScript 前端开发
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
JavaScript数据类型全解:编写通用函数,精准判断各种数据类型
12 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
297 0
|
5天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
13 1