JS中的原始(Primitive)类型与对象(Object)类型

885 阅读3分钟

1、原始(Primitive)类型

在JavaScript中,存在6种原始值,分别是:布尔(boolean)、空(null)、(未定义)undefined、数字(number)、字符串(string)、ES6新增的数据类型(symbol)。

首先原始类型存储的都是值,是没有函数可以调用的,例如:undefined.toString()

如果是在 '1'.toString( ) 的情况下是可以使用的,但是 '1' 已经不是原始类型了,它被强制转换成了 String 类型,也就是对象类型,所以能调用 toString 函数。

还有 number 类型是浮点类型的,在某种情况下可能不尽人意,比如 0.1 + 0.2 !== 0.3,因为计算机只认识二进制,在进行运算时,需要将其他进制的数值转换成二进制,然后再进行计算。

        

IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持53位二进制位,所以两者相加后,因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了 0.30000000000000004,所以在进行算术计算时会产生误差。

string 类型是不可改变的,无论你在string类型上调用任何方法,都不会对值有改变。

关于null,虽然 typeof null 会输出 object,但是其实是js在最初的版本使用32位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,而null表示全为零,所以将它错误的判断为 object,虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来。

2、对象(Obcject)类型

在JavaScript中,除了原始类型其余都是对象类型了。它们的不同之处在于原始类型储存的是值,对象类型储存的是地址(指针)。当你创建一个对象类型时,计算机会在内存中帮我们开劈一个空间来存放值,但是你需要找到这个空间,这个空间会拥有一个地址(指针)。

const a = [];

对于常量 a 来说,假设它的内存地址(指针)为 #001,那么在地址 #001 的位置存放了值 [],常量 a 存放了地址(指针),再看以下代码:

const a = [];
const b = a;
b.push(1);

当把变量赋值给另外一个变量时,复制的是原本变量的地址(指针),也就是说当前的b存放的地址(指针)也是 #001,当进行数据修改时,就会改变存放的地址(指针) #001 上的值,也就导致了两个变量的值都发生了改变。

如果函数的参数是对象的情况下:

function fun(person){
  person.age = 26;
  person = {
    name: 'xxx',
    age: 28
  };
   return person;
};

const p1 = {
  name: 'xyz',
  age: 25
};
const p2 = fun(p1);

console.log(p1); // -> 打印出什么?
console.log(p2); // -> 打印出什么?

对于输出结果是什么?先来解析一番:

  • 首先,函数传参是传递对象地址(指针)的副本
  • 到函数内部修改属性这步,p1的值也被修改了
  • 当重新为 person 分配了一个对象时就出现了分歧,如下图

结果就是 person 拥有了一个新的地址(指针),也就和p1没有任何关系了,导致了最终的两个变量的值是不同的。