一、基本数据类型

1-1 六种基本数据类型

number、string、boolean、null、undefined、symbol

1-2 基本数据类型概念

  1. 首先基本数据类型存储的都是值,是没有函数可以调用的,比如 undefined.toString(),’1’.toString() 可以使用是因为 ‘1’ 在调用 toString 的时候被强制转换成了 String 对象类型
  2. 虽然 typeof null 是 object,但是 null 不是对象类型,这只是 JS 存在的一个悠久 Bug。在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000 开头代表是对象,然而 null 表示为全零,所以将它错误的判断为 object 。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来

    1-3 装箱、拆箱操作

  3. 基本类型 number、string、boolean对应的内置对象分别是 Number(),String(), Boolean()

  4. 装箱:就是把基本类型转变为对应的对象。装箱分为隐式和显示

    1. // 隐式装箱: 每当读取一个基本类型的值时,后台会创建一个该基本类型所对应的对象。
    2. // 在这个基本类型上调用方法,其实是在这个基本类型对象上调用方法。
    3. // 这个基本类型的对象是临时的,它只存在于方法调用那一行代码执行的瞬间,执行方法后立刻被销毁。
    4. let num = 123;
    5. num.toFixed(2); // '123.00'
    6. // 当基本数据类型调用方法时候,后台的真正步骤为
    7. let c = new Number(num);
    8. c.toFixed(2);
    9. c = null;
    10. // 显式装箱: 通过内置对象 Boolean、Object、String 等可以对基本类型进行显示装箱。
    11. var obj = new String('123');
  5. 拆箱:拆箱与装箱相反,把对象转变为基本类型的值。

    1. let numObject = new Number(1)
    2. let strObject = new String('1')
    3. console.log(numObject) // Number {1}
    4. console.log(strObject) // String {'1'}
    5. // 拆箱
    6. numObject.valueOf() // 1;
    7. strObject.toString() // '1';

    1-4 null 和 undefined

  6. undefined 表示“未定义”

    1. // undefined 出现的五种情况
    2. // 1.真的是没定义(仅typeof可用),其他情况直接报错
    3. console.log(typeof a); // "undefined"
    4. // 2.定义了但没赋值
    5. let a;
    6. console.log(a); // undefined
    7. // 3.直接赋值undefined或返回undefined
    8. let a= undefined;
    9. console.log(a); // undefined
    10. // 4.函数空return或者干脆没有return
    11. function blueFn1(){
    12. return;
    13. }
    14. console.log(blueFn1()) // undefined
    15. // 5.没有对应属性
    16. const blue={age: 18, gender: 'male'};
    17. console.log(blue.height); //undefined——因为就没有叫height的东西
  7. null 表示“空指针”, null 不会平白无故出现,是主动使用时候出现

  8. 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

  1. <a name="TqEeK"></a>
  2. ## 二、引用数据类型
  3. <a name="nm8YJ"></a>
  4. #### 2-1 三种引用数据类型
  5. - object,array,function
  6. - 也有一种说法就是除了基本数据类型,其他都是都是对象,数组是对象,方法是对象
  7. <a name="LWKH7"></a>
  8. ## 三、基本数据类型和引用数据类型的区别
  9. <a name="DTAfa"></a>
  10. #### 3-1 声明变量时内存分配不同
  11. - 基本数据类型的变量和值都是保存在栈内存中
  12. - 引用数据类型的变量是一个保存在栈内存中的指针,值是保存在堆内存中的对象
  13. 原因:引用数据类型值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。放在栈空间中的值是该对象存储在堆中的地址(指针)。(指针)的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响
  14. <a name="jcztx"></a>
  15. #### 3-2 访问机制不同
  16. - 在JavaScript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是传说中的按引用访问
  17. - 而基本数据类型的值则是可以直接访问到的
  18. <a name="YQVBI"></a>
  19. #### 3-3 复制变量不同
  20. - 复制基本数据类型变量是将原始值的副本赋给新变量,此后两个变量是完全独立的,只是值相同而已
  21. - 复制引用数据类型的变量,是将该变量的内存地址赋给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们其中任何一个做出改变都会反映到另一个变量上
  22. <a name="UIiz3"></a>
  23. #### 3-4 参数传递不同
  24. - 基本数据类型变量当作参数,只是把变量里的值传递给参数,之后参数和这个变量互不影响
  25. - 引用数据类型变量当作参数,传递的值就是这个内存地址(指针),参数和传递的变量指向同一个对象
  26. <a name="nzDy1"></a>
  27. ## 四、案例
  28. <a name="uZqZS"></a>
  29. #### 4-1 函数参数是对象
  30. ```javascript
  31. function test(person) {
  32. person.age = 26
  33. person = {
  34. name: 'yyy',
  35. age: 30
  36. }
  37. return person
  38. }
  39. const p1 = {
  40. name: 'yck',
  41. age: 25
  42. }
  43. const p2 = test(p1)
  44. console.log(p1) // { name:'yck', age:26 }
  45. console.log(p2) // { name:'yyy', age:30 }
  • 首先,函数传参是传递对象指针的副本
  • 到函数内部修改参数的属性这步, p1 的值也被修改了
  • 重新为 person 分配了一个对象,与p1没有任何关系

    未命名文件.png
    五、typeof vs instanceof

    5-1 typeof

  • typeof 对于基本数据类型类型来说,除了 null 都可以显示正确的类型

    1. typeof 1 // 'number'
    2. typeof '1' // 'string'
    3. typeof undefined // 'undefined'
    4. typeof true // 'boolean'
    5. typeof Symbol() // 'symbol'
    6. typeof null //object
  • typeof 对于引用数据类型类型来说,除了函数都可以显示object

    1. typeof [] // 'object'
    2. typeof {} // 'object'
    3. 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

  1. - 如果需要 instanceof 来判断基本数据类型,可以通过Symbol.hasInstance
  2. ```javascript
  3. class PrimitiveString {
  4. static [Symbol.hasInstance](x) {
  5. return typeof x === 'string'
  6. }
  7. }
  8. console.log('hello world' instanceof PrimitiveString) // true

Symbol.hasInstance 是一个能让我们自定义 instanceof 行为的东西,以上代码等同于 typeof ‘hello world’ === ‘string’,所以结果自然是 true 了。这其实也侧面反映了一个问题, instanceof 也不是百分之百可信的。