JS数据类型(1):数据类型与内存空间

数据类型是 JavaScript 中最基础的知识点,咱们在平常的开发中,无时无刻不在用到数据类型相关的知识。在面试中,数据类型也是最基础的考点,本文将会以几道常见的面试题开头,依次解释其中须要咱们掌握的知识点。git

关于数据类型与数据存放相关的面试题:github

  1. JavaScript 中变量类型分为几种,区别是什么?
  2. 基本数据类型和引用数据类型的区别?
  3. 不一样数据类型分别存放在哪里?
  4. 栈和堆的区别是什么?分别怎么存储数据?
  5. 代码题。结果以及为何?
var a = { age: 19 };
var b = a;
a = null;
console.log(b); // ?
复制代码
  1. const 定义的值能修改么?
const obj = {
  name: 'zs',
  age: 20
};

obj.age = 30;
console.log(obj); // ?
复制代码

这些问题都比较基础,可是若是你还有模棱两个的地方,不妨再仔细阅读一下下面的内容。面试

一. 数据类型

众所周知,JavaScript 中有 7 种数据类型,分别是:Undefined、Null、Boolean、Number、String、Symbol 以及 Object。微信

其中,前 6 种咱们称之为基本数据类型,最后一种咱们称之为引用数据类型ui

另外一方面,在 JavaScript 中,一个变量能够随时持有任何类型的值。好比:spa

var a = '3';
a = 50;
复制代码

这代表:JavaScript 中的变量是没有类型的,只有值才有。3d

二. 栈、堆以及数据存放

简单来讲,在 JavaScript 中,每个数据都须要有它所对应的内存空间。而内存空间主要分为两种:栈内存(Stack)堆内存(Heap)code

栈内存通常用来存放基本数据类型的值(Undefined、Null、Boolean、Number、String、Symbol)。栈内存由系统自动分配内存空间,存储值的大小固定,空间小,运行效率更高。cdn

堆内存用来存放引用数据类型的值(对象)。当咱们声明了一个引用类型的值(对象)以后,这个引用类型的值(对象)保存在堆内存中。另外一方面,这个值(对象)的地址会被保存在栈内存中,用来引用这个对象。同时,堆内存存储的值大小不定,能够动态调整,空间大,运行效率更低。对象

为了形象的说明,咱们把下面的例子用图来表示一下:

var c = { name: 'zs' }; // 引用数据类型
var b = 'abc'; // 基本数据类型
var a = 10; // 基本数据类型
复制代码

经过上面的解释以及图示,咱们能够知道:

1. 基本数据类型是按值访问的,能够操做保存在变量中实际的值。

2. 引用数据类型是按引用访问的。

三. 赋值与传递

由于保存基本数据类型和引用数据类型的方式不一样,因此从一个变量向另外一个变量复制基本数据类型值和引用数据类型值时,也存在不一样。

对于基本数据类型的值而言,咱们老是经过值复制的方式来赋值和传递。

var num1 = 10;
var num2 = num1;
num1 = 30;
console.log(num2); // 10
复制代码

在这个例子中,10 是一个 Number 类型的值,变量 num1 持有该值的一个副本。当咱们将 num1 的值赋值给 num2 时,其实是新开辟了一块内存空间,此时 num2 也持有该值的一个副本。这两个变量的任何操做,都不会互相影响。

而对于引用数据类型而言,咱们老是经过引用复制的方式来赋值和传递。咱们用文章开头的代码题来举例:

var a = { age: 19 };
var b = a;
a = null;
console.log(b);
复制代码

由于变量 a 保存的是一个引用类型的值(对象),因此当把变量 a 的值赋值给变量 b 时,其实是复制了 a 引用(也就是指向堆内存的地址),此时 ab 指向同一块内存空间。当代码执行 a = null 时,其实是将清除了这个引用,变量 b 的指向不会发生变换。因此打印 b 的结果依旧是 { age: 19 }

这里咱们须要明确如下两点:

1. ab 仅仅是指向 { age: 19 },而并不是持有。

2. 引用指向的是值自己而非变量,因此一个引用没法更改另外一个引用的指向。

四. const 定义一个常量,能够修改么?

咱们知道,const 声明一个只读常量。一旦声明,变量的值不能修改。但看到下面的例子,是否会有一丝疑惑?

const obj = {
  name: 'zs',
  age: 20
};

obj.age = 30;
console.log(obj); // { name: 'zs', age: 30 };
复制代码

咱们发现,代码并无报错。其实这个缘由也很简单,就像上面画的那张图同样,变量 obj 其实保存的是一个引用,也就是一个地址,当咱们修改对象内部的值时,变量保存的地址并无发生变化,因此是不会报错的。

若是咱们修改代码为:

obj = null;
复制代码

此时,const 声明的变量中保存的地址就会发生变化,因此才会报错。

五. 总结

本文主要介绍了 JavaScript 中最基础的概念数据类型,区分了基本数据类型与引用数据类型以及它们存放方式上的差别。正是由于这些差别,因此它们在赋值和传递上也有不一样的特色。

最后,咱们抛出两个问题:

  1. 为何一个基本类型的值,能够像对象同样访问属性和方法?好比:
const a = '123';
a.length; // 3
复制代码
  1. 既然基本数据类型能够访问属性和方法,为何 1.toString() 会报错?不是应该变为 "1" 么?

下期,咱们来聊聊数据类型中的封装对象。

以上内容,若有错误,欢迎指正。

文章会在 Github ,以及微信公众号(野蛮成长实验室)首发,欢迎关注和 Star。

相关文章
相关标签/搜索