JavaScript底层数据结构使用的是 栈( Stack) 和 堆(Heap)
JavaScript基本类型数据都是直接按值存储在栈中的(Undefined
、Null
、不是new
出来的布尔、JavaScript基本类型
数据都是直接按值存储在栈中的(Undefined
、Null
、不是new
出来的布尔、数字和字符串),每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说 ,更加容易管理内存空间。
JavaScript引用类型
数据被存储于堆中 (如对象、数组、函数等,它们是通过拷贝和new
出来的)。其实,说存储于堆中,也不太准确,因为,引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。
2022.2.11 以上新增
1.值类型(基本数据类型)
string
number
boolean
null
undefined
symbol: 唯一值(字符串key)
bigint:大范围的整数值
值类型是存储在栈(stack)中的简单数据,存储在变量处的就是指
2.引用类型
Object
Set(新增 Set.prototype.__proto__ === Object.prototype)
Map(新增 Map.prototype.__proto__ === Object.prototype)
Array
Function
RegExp
Date
其实array和function是object的子类
存储在堆(heap)中的对象,也就是说,存储在变量处的是一个指针,指向存储对象的内存
3.值类型和引用类型的赋值
3.1值类型赋值,直接将值复制一份
var num1 = 10
var num2 = num1
在内存中的体现:
3.2引用类型赋值,是将地址复制一份,最后指向同一个对象
var p = {name:"张三", age:19};
var p1 = p;
在内存的体现:
4.值传递和引用传递
JS的基本类型是值传递的,意思就是一个基本数据类型的变量赋值给一个变量,传递的是存储在变量中的值;修改其中的一个值,不会影响另外一个
对于复杂数据类型是引用传递,意思就是一个复杂数据类型的变量赋值给另外一个变量,传递的是存储在变量中的地址,两者同时指向同一块内存,修改其中一个的值会影响另外一个
5.引出var、let、const
使用var
声明的变量,其作用域为该语句所在的函数中,且存在变量提升现象
使用let
声明的变量,其作用域为该语句的代码块内,不存在变量提升
使用const
声明的常量,在后面出现的代码中不能再修改该常量的值
let的出现解决了
1.JS没有块级作用域的问题
2.解决循环体内的回调问题
6.判断js数据类型的4中方法[1]
1. typeof
2. instanceof
3. constructor
4. toString
typeof
typeof
是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 8 种:undefined、string、number、boolean、symbol、biginit、object、function 等。
- 对于基本类型,除 null 以外,均可以返回正确的结果。
- 对于引用类型,除 function 以外,一律返回 object 类型
typeof undefined; //undefined 有效
typeof ''; // string 有效
typeof 1; // number 有效
typeof true; //boolean 有效
typeof null; //object 无效
typeof Symbol(); // symbol 有效
typeof BigInit(1); // biginit 有效
typeof [] ; //object 无效
typeof new Function(); // function 有效
typeof new Date(); //object 无效
typeof new RegExp(); //object 无效
instanceof
-
instanceof
是用来判断 A 是否为 B 的实例,表达式为:A instanceof B
,如果 A 是 B 的实例,则返回 true,否则返回 false。 在这里需要特别注意的是:instanceof 检测的是原型; -
instanceof
只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型
constructor
当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。如下所示:
当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F
toString
toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型
对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用
参考连接: 判断JS数据类型的四种方法
-
判断js数据类型的4中方法 ↩