JavaScript中的类型 | 刷题打卡

276 阅读3分钟

一、ECMAScript标准

根据ECMAScript的标准,JavaScript(ES5)的类型定义如下:

  • 5种基本的数据类型:StringNumberBooleannullundefined

  • 1种复杂的数据类型:Object

可以通过typeof操作符判断数据类型,typeof操作符可能会返回如下字符串:

  • undefined(undefined

  • boolean(Boolean的实例)

  • number(Number的实例)

  • object(Object/Array/RegExp/Date的实例,或者null

  • function(Function的实例)

二、值类型和引用类型

  • 值类型:实际上就是5种基本的数据类型:String、Number、Boolean、null、undefined

  • 引用类型:Object(包含:Array、Function)

三、== 与 === 的区别

  1. 对于String、Number等值类型,===== 是有区别的:

  2. 不同类型之间比较,==会先做隐式转化(转化成同一类型后的值)再比较,而===如果类型不同,其结果就是不等。

  3. 同类型比较时,直接进行值比较, ===== 的结果一样。

// 测试1:值类型

let str = '42';
let num1 = 42;
let num2 = 42;
console.log(str == num1);   // true, 在比较时进行了隐式类型转换
console.log(str === num1);  // false 说明首先比较了类型,类型不等,所以为 false
console.log(num1 === num2); // true 同类型比较,直接比较值 
  1. 对于Array、Object等引用类型,=====没有区别的,因为都是直接比较保存的内存指针地址。
// 测试2:引用类型
let o1 = {};
let o2 = o1;
let o3 = {};

console.log(o1 == o2);   // true
console.log(o1 === o2);  // true
console.log(o1 == o3);   // false
console.log(o1 === o3);  // false 
  1. 基础类型与引用类型比较时,=====有区别的。

  2. 对于 ==,将引用类型转换为基本类型,进行**“值”**比较。

  3. 因为类型不同,===结果为false

// 测试3:引用类型和值类型比较
let array = [1, 2, 3];
let fn = function() {};
let object = {
  name: 'Tom'
};
let string = '1,2,3';
let string2 = `function() {}`;

console.log(array == string);  // true 比较时进行了类型转换
console.log(fn == string2);    // true
console.log(object == '[object Object]'); // true 

结论:==会在比较时强制类型转换,因此,当我们需要严格判断两个变量的类型和值时,请使用===

  1. 根据上面一个例子,我们会注意到,在执行比较时,隐式的进行类型转换。那么隐式的具体是指什么呢?那就是:object.toString()。所以,我们可以得出对象类型的判断终极武器:
// 测试4:通用的派生对象类型判断方法
Object.prototype.toString.call([]) // "[object Array]" 还可以直接用静态方法 Array.isArray 来进行判断
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(new Date()) // "[object Date]"
Object.prototype.toString.call(new RegExp()) // "[object RegExp]"
Object.prototype.toString.call(new Map()) // "[object Map]"
Object.prototype.toString.call(new Promise(function() {})) // "[object Promise]"
Object.prototype.toString.call(Symbol()) // "[object Symbol]" 

四、引用类型带来的问题

由于引用类型存储的是内存中的一个指针地址,所以当我们修改了某个值后,这个值的变化会直接导致另外一个值的变化,如果不明白其中的原理,会在平时开发中遇到一些困惑。

例子一:Object

// 测试5:对象的赋值

let obj1 = {
  name: {
    firstName: 'Tom',
    lastName: 'Jerry',
  },
  age: 42,
};

let obj2 = obj1;

obj2.name.firstName = 'Foo';

console.log(obj1 === obj2); // true
// 2个对象引用的是同一个地址,赋值会同时受影响
console.log(obj1.name.firstName); // Foo
console.log(obj2.name.firstName); // Foo 

例子二:Array

// 测试5:数组的赋值
let arr1 = [1, 2, 3, 4, 5];
let arr2 = arr1;
arr2[0] = 0;
console.log(arr1); // [0, 2, 3, 4, 5] 

例子三:Function

// 测试6:函数的赋值
function Fn(name) {
  this.name = name;
}
Fn.prototype.getName = function () {
  return this.name;
};

let Fn2 = Fn;
Fn2.prototype.getName = function () {
  return `${this.name} - new`;
};

console.log(Fn2 === Fn); // true

var foo = new Fn('Bar');
console.log(foo.getName()); // Bar - new