一、基本数据类型
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或返回undefined
let a= undefined;
console.log(a); // undefined
// 4.函数空return或者干脆没有return
function 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 函数参数是对象
```javascript
function test(person) {
person.age = 26
person = {
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
```javascript
class 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 也不是百分之百可信的。