类型判断

  • 源码地址:/src/shared/util.js
  • 描述:用于判断、检查、输出参数的类型

源码

1. isPrimitive


  • JS 原始类型:

    • Null, Undefiend, String, Number, Boolean, Object, Symbol
  • JS 引用类型:

    • Object、Array、Function
  • null

    • 当一个对象指向空了,此时可以赋值为 null

    • 如果想要一个变量值为 Null , 只能在变量定义的时候让这个变量的值为 Null 才行。

  • undefined:

    • 当一个变量声明了,但没有赋值,结果是 undefined

    • 当函数没有明确返回值,却接收了,结果也是 undefined

    • 如果一个变量是 undefined,然后和一个数字进行计算,那么结果是 NaN

  • NaN

    • NaN 是 Number 类型

    • NaN 属性是代表非数字值的特殊值,该属性用于指示某个值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**   
  * Check if value is primitive. 
  * 
  * primitive [ˈprɪmətɪv] 原始的 
  * 
  * 检查 value 是否是原始类型, 
  * 如果没有通过校验,说明参数是空的 -> null ,'' ,undefined 
  */ 
export function isPrimitive (value: any): boolean %checks {    
  return (      
    typeof value === 'string' ||      
    typeof value === 'number' ||      
    // $flow-disable-line      
    typeof value === 'symbol' ||      
    typeof value === 'boolean'    
  ) 
}

2. _toString


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**   
  * Get the raw type string of a value, e.g., [object Object]. 
  * 
  * 所有类型都继承 Object 
  * 
  * 如:String,Array 可以直接调用 
  * 
  * Array.prototype.toString -> "" 
  *
  * 但这些类型都自己重写了 toString, 所以他们输出的是字符串而不是类型 
  * 
  * Object.prototype.toString() 是可以输出类型的 
  * 
  * 所以我们删除掉 基本类型 自己重写的 toString 后即可直接调用 
  * Object.prototype.toString 
  * 
  * 如: delete Array.prototype.toString 
  * 
  * Array.prototype.toString() -> [object Array] 
  */ 
const  _toString  =  Object.prototype.toString

3. toRawType


1
2
3
4
5
6
7
8
9
10
11
12
/**   
  * 获取字符串类型 
  * 
  * 通过 _toString.call 可以获取 value 的类型 
  * 
  * 如:_toString.call([]) -> [object Array] 
  * 
  * 通过 slice 截取字符串,获取 Array 
  */ 
export function toRawType (value: any): string {    
  return _toString.call(value).slice(8, -1
}

解析

[ toString ]


  • JS 中所有对象都继承于 Object
1
2
3
4
5
6
7
8
String instanceof Object //-> true   
Number instanceof Object //-> true 
RegExp instanceof Object //-> true 
Array instanceof Object //-> true 
Symbol instanceof Object //-> true 
Boolean instanceof Object //-> true 
Function instanceof Object //-> true 
Math instanceof Object //-> true
  • 因为所有对象都继承与 Object, 故所有对象都可以使用 Object 原型上的方法

  • 根据上述内容,可得以下结论

    • 每个给都有一个 toString() 方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。

    • 默认情况下,toString() 方法被每个 Object 对象所继承。

    • 若果此方法在自定义对象中未被覆盖,toString() 返回 “[object type]”,其中 type 是对象的类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 默认情况下   
const obj = new Object(); 
obj.toString(); //-> [object Object] 
// 原生对象覆盖 
[1,2].toString(); //-> '1,2' 
// 移除原生对象自身 toString 
// 1. 检查自身否拥有自定义 toString 
Array.prototype.hasOwnProperty('toString'//-> true 
// 2. 移除自身自定义的 toString 
delete Array.prototype.toString//-> true 
// 3. 检查自身否还拥有自定义 toString 
Array.prototype.hasOwnProperty('toString'//-> false 
// 4. 调用 toString 方法 
[1,2].toString(); //-> [object,Array]
  • 覆盖默认的 Object.prototype.toString
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 创建一个 Dog 类   
function Dog(name,color,sex){ 
  this.name = name;    
  this.color = color;    
  this.sex = sex; 

const dog = new Dog('xiao hei','black','female'); 
// 如果此时 dog 对象调用 toString() 
// 他将会返回从 Object 继承来的 toString 方法的返回默认值 
dog.toString(); //-> [object Object] 
// 定义一个 dogToString 方法来覆盖默认的 toString() 方法 
Dog.prototype.toString = function dogToString() { 
  return return `Dog ${this.name} is a ${this.sex} ${this.color}`

// 此后再调用 dog.toString 方法,将会一直调用 dogToString 方法 
dog.toString(); //-> "Dog xiao hei is a female black"

[ toString 原理 ]


  • 当 Object.prototype.toString 被调用时,会执行以下操作:

    1. 获取 this 对象的 [[Class]] 属性值

    2. 计算出三个字符串的连接字符串 –> “[object”, 第一步操作结果 Result(1), “]”

    3. 返回第二部的操作结果 Result(2)

  • [[Class]] 是一个内部属性,所有的对象(原生对象和宿主对象)都拥有该属性。

  • 在规范中 [[Class]] 的定义

内部属性 描述
[[Class]] 一个字符串值,表名了该对象的类型

[使用 toString 检测对象类型]


可以通过 toString() 来获取每个对象的类型。

为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用,传递要检查的对象作为第一个参数,称为 thisArg

1
2
3
4
5
6
7
8
9
Object.prototype.toString.call(123//->[object Number]   
Object.prototype.toString.call('123'//-> [object String] 
Object.prototype.toString.call(true//-> [object Boolean] 
Object.prototype.toString.call({}) //-> [object Object] 
Object.prototype.toString.call([]) //-> [object Array] 
Object.prototype.toString.call(function(){}) //-> [object Function] 
Object.prototype.toString.call(Math//-> [object Math] //Since JavaScript 1.8.5 
Object.prototype.toString.call(null//-> [object Null] 
Object.prototype.toString.call(undefined//-> [object Undefined]

[ 语言标准 ]


ECMAScript 5.1 (ECMA-262)

15.2.4.2 Object.prototype.toString ( )
When the toString method is called, the following steps are taken:
If the this value is undefined, return “[object Undefined]”.
If the this value is null, return “[object Null]”.
Let O be the result of calling ToObject passing the this value as the argument.
Let class be the value of the [[Class]] internal property of O.
Return the String value that is the result of concatenating the three Strings “[object “, class, and “]”.

如 ECMAScript 5 和随后的 Errata 中所定义,

从 JavaScript 1.8.5 开始 toString() 调用 null 返回 [object Null], undefined 返回 [object Undefined]。

ES 6 调用 toString 可以检测 函数参数 arguments 返回 [object Arguments] , Error 返回 [object Error]


类型判断
https://blog.pangcy.cn/2022/11/18/前端编程相关/前端框架与库/Vue/Vue2 源码分析/类型判断/
作者
子洋
发布于
2022年11月18日
许可协议