一、基本数据类型
1-1 六种基本数据类型
number、string、boolean、null、undefined、symbol
1-2 基本数据类型概念
- 首先基本数据类型存储的都是值,是没有函数可以调用的,比如 undefined.toString(),’1’.toString() 可以使用是因为 ‘1’ 在调用 toString 的时候被强制转换成了 String 对象类型
 虽然 typeof null 是 object,但是 null 不是对象类型,这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来
1-3 装箱、拆箱操作
基本类型 number、string、boolean对应的内置对象分别是 Number(),String(), Boolean()
装箱:就是把基本类型转变为对应的对象。装箱分为隐式和显示
// 隐式装箱: 每当读取一个基本类型的值时,后台会创建一个该基本类型所对应的对象。// 在这个基本类型上调用方法,其实是在这个基本类型对象上调用方法。// 这个基本类型的对象是临时的,它只存在于方法调用那一行代码执行的瞬间,执行方法后立刻被销毁。let num = 123;num.toFixed(2); // '123.00'// 当基本数据类型调用方法时候,后台的真正步骤为let c = new Number(num);c.toFixed(2);c = null;// 显式装箱: 通过内置对象 Boolean、Object、String 等可以对基本类型进行显示装箱。var obj = new String('123');
拆箱:拆箱与装箱相反,把对象转变为基本类型的值。
let numObject = new Number(1)let strObject = new String('1')console.log(numObject) // Number {1}console.log(strObject) // String {'1'}// 拆箱numObject.valueOf() // 1;strObject.toString() // '1';
1-4 null 和 undefined
undefined 表示“未定义”
// undefined 出现的五种情况// 1.真的是没定义(仅typeof可用),其他情况直接报错console.log(typeof a); // "undefined"// 2.定义了但没赋值let a;console.log(a); // undefined// 3.直接赋值undefined或返回undefinedlet a= undefined;console.log(a); // undefined// 4.函数空return或者干脆没有returnfunction blueFn1(){return;}console.log(blueFn1()) // undefined// 5.没有对应属性const blue={age: 18, gender: 'male'};console.log(blue.height); //undefined——因为就没有叫height的东西
null 表示“空指针”, null 不会平白无故出现,是主动使用时候出现
- null的本质是 0,undefined 的本质是特殊对象 ```javascript Number(null); //0 Number(undefined); //NaN
 
12 + null; //12 12 + undefined; //NaN
-5 < null; //true ——null是0,-5<0 -5 < undefined; //false
<a name="TqEeK"></a>## 二、引用数据类型<a name="nm8YJ"></a>#### 2-1 三种引用数据类型- object,array,function- 也有一种说法就是除了基本数据类型,其他都是都是对象,数组是对象,方法是对象<a name="LWKH7"></a>## 三、基本数据类型和引用数据类型的区别<a name="DTAfa"></a>#### 3-1 声明变量时内存分配不同- 基本数据类型的变量和值都是保存在栈内存中- 引用数据类型的变量是一个保存在栈内存中的指针,值是保存在堆内存中的对象原因:引用数据类型值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。放在栈空间中的值是该对象存储在堆中的地址(指针)。(指针)的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响<a name="jcztx"></a>#### 3-2 访问机制不同- 在JavaScript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问- 而基本数据类型的值则是可以直接访问到的<a name="YQVBI"></a>#### 3-3 复制变量不同- 复制基本数据类型变量是将原始值的副本赋给新变量,此后两个变量是完全独立的,只是值相同而已- 复制引用数据类型的变量,是将该变量的内存地址赋给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们其中任何一个做出改变都会反映到另一个变量上<a name="UIiz3"></a>#### 3-4 参数传递不同- 基本数据类型变量当作参数,只是把变量里的值传递给参数,之后参数和这个变量互不影响- 引用数据类型变量当作参数,传递的值就是这个内存地址(指针),参数和传递的变量指向同一个对象<a name="nzDy1"></a>## 四、案例<a name="uZqZS"></a>#### 4-1 函数参数是对象```javascriptfunction test(person) {person.age = 26person = {name: 'yyy',age: 30}return person}const p1 = {name: 'yck',age: 25}const p2 = test(p1)console.log(p1) // { name:'yck', age:26 }console.log(p2) // { name:'yyy', age:30 }
- 首先,函数传参是传递对象指针的副本
 - 到函数内部修改参数的属性这步, p1 的值也被修改了
 - 

五、typeof vs instanceof5-1 typeof
 typeof 对于基本数据类型类型来说,除了 null 都可以显示正确的类型
typeof 1 // 'number'typeof '1' // 'string'typeof undefined // 'undefined'typeof true // 'boolean'typeof Symbol() // 'symbol'typeof null //object
typeof 对于引用数据类型类型来说,除了函数都可以显示object
typeof [] // 'object'typeof {} // 'object'typeof console.log // 'function'
5-2 instanceof
如果想判断一个对象的正确类型,首选 instanceof,因为他的内部机制是通过原型链来判断的 ```javascript const p1 = new Person() p1 instanceof Person // true
var str = ‘hello world’ str instanceof String // false
var str1 = new String(‘hello world’) str1 instanceof String // true
- 如果需要 instanceof 来判断基本数据类型,可以通过Symbol.hasInstance```javascriptclass PrimitiveString {static [Symbol.hasInstance](x) {return typeof x === 'string'}}console.log('hello world' instanceof PrimitiveString) // true
Symbol.hasInstance 是一个能让我们自定义 instanceof 行为的东西,以上代码等同于 typeof ‘hello world’ === ‘string’,所以结果自然是 true 了。这其实也侧面反映了一个问题, instanceof 也不是百分之百可信的。
