前言
- JS中的基本数据类型有哪些?基本数据类型和引用数据类型的区别?
数据类型
在JavaScript中,数据类型整体上来讲可以分为两大类:基本类型和引用数据类型
基本数据类型一共有6种
String:字符串Number:数字Boolean:布尔值Null:空值Undefined:未定义Symbol:符号(ES6新增)
引用数据类型一共有1种
Object:对象(包括数组、函数、正则等)
基本数据类型的值又被称之为原始值或简单值,而引用数据类型的值又被称之为复杂值或引用值。
简单值(原始值)
简单值是表示JavaScript中可用的数据或信息的最底层形式或最简单形式。简单类型的值被称为简单值,是因为它们是不可细化的。
也就是说,数字是数字,字符串是字符串,布尔值是true或false,null和undefined就是null和undefined。这些值本身很简单,不能够再进行拆分。
由于简单值的数据大小是固定的,所以简单值的数据是存储于内存中的栈区里面的。
栈区的特点是先进后出,后进先出,如下图:
简单值示例:
var str = 'hello world';
var num = 123;
var bool = true;
var nul = null;
var und = undefined;
console.log(typeof str); // string
console.log(typeof num); // number
console.log(typeof bool); // boolean
console.log(typeof nul); // object
console.log(typeof und); // undefined
这里面null比较特殊,打印出来是object,这是由于历史原因所遗留下来的问题。
是来源于JavaScript从第一个版本开始时的一个bug,并且这个bug无法被修复。因为修复会破坏现有的代码。
具体原因是因为不同的对象在底层都表现为二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型,null的二进制全部为0,自然前三位也是0,所以执行typeof值会返回object。
另外,当我们打印null == undefined的时候,返回的是true,这也是面面试时经常会被问到的一个问题。
这两个值都表示"无"的意思。
通常情况下,当我们试图访问某个不存在的或者没有赋值的变量时,就会得到一个undefined值。JavaScript会自动将声明是没有进行初始化的变量设为undefined。
而null值表示空,null不能通过Javascript来自动赋值,也就是说必须要我们自己手动来给某个变量赋值为null。
那么为什么JavaScript要设置两个表示"无"的值呢?
这其实也是因为历史原因。
1995年JavaScript诞生时,最初像Java一样,只设置了 null 作为表示"无"的值。根据C语言的传统,null被设计成可以自动转为0。
但是,JavaScript的设计者,觉得这样做还不够,主要有以下两个原因。
-
null像在Java里一样,被当成一个对象。但是,JavaScript的数据类型分成原始类型(primitive)和复合类型(complex)两大类,作者觉得表示"无"的值最好不是对象。
-
Javascript的最初版本没有包括错误处理机制,发生数据类型不匹配时,往往主是自动转换类型或者默默地失败。作者觉得,如果null自动转为0,很不容易发现错误。
因此,作者又设计了一个undefined。这里注意:先有null后有undefined,undefined是为了填补之前的坑。
JavaScript的最初版本是这样区分的:
-
null是一个表示"无"的对象,转为数值时为0;
典型用法是
- 作为函数的参数,表示该函数的参数不是对象。
- 作为对象原型链的终点。
-
undefined是一个表示"无"的原始值,转为数值时为NaN。
典型用法是
- 变量被声明了,但没有赋值时,就等于undefined。
- 调用函数时,应该提供的参数没有提供,该参数等于undefined。
- 对象没有赋值的属性,该属性的值为undefined。
- 函数没有返回值时,默认返回undefined。
复杂值(引用值)
在JavaScript中,对象就是一个复杂值。因为对象可以向下拆分,拆分成多个简单值或者复杂值。
复杂值在内存中的大小是未知的,因为复杂值可以包含任何值,而不是一个特定的已知值,所以复杂值的数据都是存储于堆区里面。
堆区的特点是先进先出,后进后出,如下图:
复杂值示例:
var obj = {
name: '张三',
age: 18
};
console.log(typeof obj); // object
访问方式
按值访问
简单值是作为不可细化的值进行存储和使用的,引用它们会转移其值。
var a = '1'
var b = a
a = null
console.log(a) // null
console.log(b) // 1
引用访问
复杂值是通过引用进行存储和操作的,而不是实际的值。创建一个包含复杂对象的变量时,其值是内存中的一个引用地址。引用一个复杂对象时,使用它的名称(即变量或对象属性)通过内存中的引用地址获取该对象值。
var obj = {}
var obj2 = obj
obj.name = '张三'
console.log(obj2.name) // 张三
比较方式
简单值采用值比较,而复杂值采用引用比较。复杂值只有在引用相同的对象(即有相同的地址)时才相等。即使是包含相同对象的两个变量也彼此不相等,因为它们并不指向同一个对象。
var obj = {}
var obj2 = {}
console.log(obj === obj2) // false
动态属性
对于复杂值,可以为其添加属性和方法,也可以改变和删除其属性和方法。但简单值不可以:
var a = 123
a.b = 456
console.log(a.b) // undefined
var obj = {}
obj.name = '张三'
console.log(obj.name) // 张三
复杂值支持动态对象属性,因为我们可以定义对象,然后创建引用,再更新对象,并且所有指向该对象的变量都会获得更新。
一个新变量指向现有的复杂对象,并没有复制该对象。这就是复杂值有时被称为引用值的原因。复杂值可以根据需求有任意多个引用,即使对象改变,它们也总是指向同一个对象。
var obj = {}
var obj2 = obj
obj.name = '张三'
console.log(obj2.name) // 张三
变量赋值
最后说一下关于变量的赋值,其实是可以分为直接赋值和引用赋值的。直接赋值,就是指将简单值赋值给变量,而引用赋值是指将一个复杂值的引用赋值给变量,这个引用指向堆区实际存在的数据。
总结
- JS中的基本数据类型有哪些?基本数据类型和引用数据类型的区别?
在JavaScript中,数据类型整体上来讲可以分为两大类:基本类型和引用数据类型
基本数据类型一共有6种
String:字符串Number:数字Boolean:布尔值Null:空值Undefined:未定义Symbol:符号(ES6新增)引用数据类型一共有1种
Object:对象(包括数组、函数、正则等)基本数据类型的值又被称之为原始值或简单值,而引用数据类型的值又被称之为复杂值或引用值。
区别:
访问方式
原始值访问的是值,引用值访问的是引用地址
比较方式
原始值比较的是值,引用值比较的是引用地址
动态属性
原始值不支持动态属性,引用值支持动态属性
变量赋值
原始值赋值的是值,引用值赋值的是引用地址