深入理解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

相关文章
|
8天前
|
JavaScript 前端开发
js变量的作用域、作用域链、数据类型和转换应用案例
【4月更文挑战第27天】JavaScript 中变量有全局和局部作用域,全局变量在所有地方可访问,局部变量只限其定义的代码块。作用域链允许变量在当前块未定义时向上搜索父级作用域。语言支持多种数据类型,如字符串、数字、布尔值,可通过 `typeof` 检查类型。转换数据类型用 `parseInt` 或 `parseFloat`,将字符串转为数值。
14 1
|
13天前
|
存储 Java 测试技术
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
【4月更文挑战第7天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
40 1
滚雪球学Java(18):解密JavaSE中的堆栈:你真的了解Java内存吗?
|
5天前
|
存储 JavaScript 前端开发
【JavaScript技术专栏】JavaScript基础入门:变量、数据类型与运算符
【4月更文挑战第30天】本文介绍了JavaScript的基础知识,包括变量(var、let、const)、数据类型(Number、String、Boolean、Undefined、Null及Object、Array)和运算符(算术、赋值、比较、逻辑)。通过实例展示了如何声明变量、操作数据类型以及使用运算符执行数学和逻辑运算。了解这些基础知识对初学者至关重要,是进阶学习JavaScript的关键。
|
6天前
|
存储 JavaScript 前端开发
JavaScript引用数据类型
JavaScript引用数据类型
|
6天前
|
JavaScript 前端开发
JavaScript 基本数据类型
JavaScript 基本数据类型
|
6天前
|
存储 缓存 JavaScript
【Web 前端】JS哪些操作会造成内存泄露?
【4月更文挑战第22天】【Web 前端】JS哪些操作会造成内存泄露?
|
6天前
|
JavaScript 前端开发
【Web 前端】JS中检测数据类型的有哪些?
【4月更文挑战第22天】【Web 前端】JS中检测数据类型的有哪些?
|
6天前
|
存储 前端开发 JavaScript
【Web 前端】JS数据类型有哪些?区别?
【4月更文挑战第22天】【Web 前端】JS数据类型有哪些?区别?
|
15天前
|
存储 JavaScript 前端开发
JavaScript的数据类型主要分为两大类:基本数据类型和引用数据类型
【4月更文挑战第20天】JavaScript的数据类型主要分为两大类:基本数据类型和引用数据类型
21 6
|
17天前
|
JavaScript 前端开发
js数据类型有几类?一共有几种?判断数据类型的方法是什么?
js数据类型有几类?一共有几种?判断数据类型的方法是什么?