【数据类型】JavaScript数据类型&聊聊Object.prototype.toString

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaoermingn/article/details/80744550

一、数据类型

JavaScript定义了7种基本数据类型:(我这么记 SSNNBUO)

  • Symbol (ES6)
  • String
  • Number
  • Null
  • Boolean
  • Undefined
  • Object

JavaScript是一种弱类型脚本语言,即定义变量时不需要声明变量的类型,在程序运作过程中会自动判断变量的类型,定义变量的方法:

  • var
  • let (ES6)
  • const (ES6)

不添加关键词var/let/const也能定义变量,此时会创建一个全局变量,且变量不会提升


二、值类型和引用类型

除了以上类型的划分,变量还分为值类型和引用类型,在传递过程中分为值传递和引用传递。值传递只会传递变量的值,引用传递会传递变量的存储地址(指针)

var a = 1,
    b = {name: 1};

var c = a; //值传递,a会赋值给c
console.log(c); // 1

c = 2;
console.log(a); // 1 值传递相当于内存中复制了一份,c和a没有关系

var d = b;
d.name = 2;
console.log(b.name); // 2 引用传递传递的是地址,所以b和d指向同一内存地址

三、判断数据类型的方法

我们很多时候需要对数据的类型进行判断,然后进行相关的操作,判断数据类型常见有以下几种方法:

  • typeof
  • instanceof
  • Object.prototype.toString.call()

四、typeof

调用typeof方法时会返回以下几种值之一:(我这么记 ssnbuof)

  • symbol
  • string
  • number
  • boolean
  • undefined
  • object
  • function
typeof Symbol(); // symbol
typeof 'abc'; // string
typeof 123; // number
typeof NaN; // number
typoef true; // boolean
typeof undefined; // undefined
typeof {a:1}; // object
typeof [1,2,3]; // object
typeof function a(){}; // function
typeof null; // object

typeof null => object 这是typeof 的一个bug,null并不是引用类型
typeof [1,2,3] => object 除了函数返回的是function,其他引用类型返回的都是object


五、instanceof

instanceof用于实例和构造函数的对应

[1,2,3] instanceof Array; // true

var a = {name: 1};
a instanceof Object; // true

六、Object.prototype.toString.call()

使用typeof无法区分null、array、date
instanceof无法运用在值类型区分
没事,我们还有一种方法,Object.prototype.toString.call()

Object.prototype.toString.call()是一种比较常用,也是比较有效的方法

var a = {name: 1};
Object.prototype.toString.call(a); // [object Object]

var b = new Date();
Object.prototype.toString.call(b); // [object Date]

Object.prototype.toString.call(null); // [object Null]

Object.prototype.toString.call(undefined); // [object Undefined]

function a(){
    console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
}

通过这种方式我们就可以解决常见问题中的类型判断

那么,为什么Object.prototype.toString.call()可以区分数据类型?


七、探索为什么Object.prototype.toString.call()可以区分数据类型

我们先来了解一下在调用Object.prototype.toString.call()的时候发生了什么

1.在ECMA5中,调用Object.prototype.toString会执行以下步骤:

这里写图片描述

(1).如果值为undefined,则返回"[object Undefiend]"

(2).如果值为null,则返回"[object Null]"

(3).将传递的值调用ToObject方法,并赋给O作为调用后的结果

(4).将O的内部属性[[Class]]的值赋给class

(5).结果返回字符串,该字符串由三个字符串"[object ", class, and "]"拼接而成

根据上面的描述我们可以看出来,主要通过对象的内置属性[[Class]]来判断

2.内置属性[[Class]]

ECMA规范中这么介绍[[Class]]
这里写图片描述
这里写图片描述

翻译:本规范针对每种内置对象定义了[[Class]]内部属性的值。对象的[[Class]]内部属性的值可以是除了。。。之外的任何字符串值。[[Class]]内部属性的值用于内部区分不同类型的对象。 请注意,除了通过Object.prototype.toString外,本规范没有提供任何方法让程序访问该值。

我们再来看规范中,在创建某种类型变量的时候,会对对象内置属性[[Class]]进行赋值

  • 创建数组时:
    这里写图片描述

  • 创建函数时:
    这里写图片描述

  • 创建字符串时:
    这里写图片描述

3.ES6中不再使用[[Class]]内置属性进行判断

最新规范中不再使用[[Class]]内置属性进行判断,在调用Object.prototype.toString时执行了以下步骤:
这里写图片描述

(这里不详细讲,有兴趣的可以去了解下)

综上,大家应该了解了为什么Object.prototype.toString.call()可以用来区分数据类型


一些问题

1.null和undefined不是对象,为什么Object.prototype.toString.call()返回的值要采用[object *]的格式

这是ES5.1规范中的修正。 在ES5之前,将null或undefined传递给toString总是导致全局对象被传递。 ES5中严格模式相关的更改会导致null和undefined被传递而不进行修改。 按照ES5的规定,将null或undefined传递给Object.prototype.toString会导致TypeError异常。 这个例外破坏了一些现有的代码,所以ES5.1修复这个规范,以防止这种情况发生。

那么,为什么toString返回null和undefined? 事实证明,很多现有的代码也期望Object.prototype.toString始终返回形式为“[object *]”的字符串。 因此,ES5.1规范中决定将传入null和undefined的值“[object Null]”和“[object Undefined]”。

2.Object.prototype.toString(‘foo’)和Object.prototype.toString.call(‘foo’)的区别

前者传入的参数实际是Object.prototype,而Object.prototype是个对象,所以始终返回’[object Object]’,其中的’foo’会被忽略;而后者通过call,硬绑定到传入的’foo’;所以千万不要把call忘了

猜你喜欢

转载自blog.csdn.net/xiaoermingn/article/details/80744550