typeof的“小秘密”

473 阅读5分钟

相信很多朋友们在开发过程中都会用到typeof去验证码判断一个变量的数据类型,但是你是否真正了解在进行typeof的过程中,浏览器到底都做了些什么,接下来就让我们研究研究。

谈一谈js中的数据类型

或许很多小伙伴看到这个问题,脑子里面很自然都会想到,js中数据类型分为基本数据类型引用数据类型
基本数据类型又包括:

- number 数字
- string 字符串
- boolean 布尔
- null 空对象指针
- undefined 未定义
- symbol 唯一值
- bigint 大数

引用数据类型:object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)。
其实在ECMAScript262中有详细给出数据类型的标准定义:

4.2 ECMAScript Overview
    ECMAScript is object-based: basic language and host facilities are provided 
by objects, and an ECMAScript program is a cluster of communicating objects. 
In ECMAScript, an object is a collection of zero or more properties each with 
attributes that determine how each property can be used—for example, when the 
Writable attribute for a property is set to false, any attempt by executed 
ECMAScript code to assign a different value to the property fails. Properties are 
containers that hold other objects, primitive values, or functions. 
A primitive value is a member of one of the following built-in types: Undefined, 
Null, Boolean, Number, String, and Symbol; an object is a member of the built-in 
type Object; and a function is a callable object. A function that is associated 
with an object via a property is called a method.

ECMAScript是基于对象的:基本语言和主机设施是由对象提供的,而ECMAScript程序是通信对象的集群。
在ECMAScript中,对象是0个或多个属性的集合,每个属性都具有决定如何使用每个属性的属性——例如,
当属性的可写属性被设置为false时,执行ECMAScript代码为属性分配不同值的任何尝试都将失败。
属性是容纳其他对象、基本值或函数的容器。原始值是以下内置类型之一的成员:
未定义、Null、布尔、数字、字符串和符号;对象是内置类型对象的成员;
函数是可调用对象。通过属性与对象关联的函数称为方法。

    ECMAScript defines a collection of built-in objects that round out the 
definition of ECMAScript entities. These built-in objects include the global object; 
objects that are fundamental to the runtime semantics of the language 
including Object, Function, Boolean, Symbol, and various Error objects; objects 
that represent and manipulate numeric values including Math, Number, and Date; 
the text processing objects String and RegExp; objects that are indexed 
collections of values including Array and nine different kinds of Typed Arrays 
whose elements all have a specific numeric data representation; keyed collections
including Map and Set objects; objects supporting structured data including the 
JSON object, ArrayBuffer, and DataView; objects supporting control abstractions 
including generator functions and Promise objects; and, reflection objects
including Proxy and Reflect.

ECMAScript定义了一个内置对象集合,它完善了ECMAScript实体的定义。这些内置对象包括全局对
象;对象是语言运行时语义的基础,包括对象、函数、布尔值、符号和各种错误对象;表示和操作数值
(包括数学、数字和日期)的对象;文本处理对象字符串和RegExp;对象,该对象是值的索引集合,包括
数组和9种不同类型的数组,其元素都具有特定的数值数据表示;键控集合,包括MapSet对象;支持
结构化数据的对象,包括JSON对象、ArrayBufferDataView;支持控制抽象的对象,包括生成器函
数和承诺对象;以及反射对象,包括代理和反射

我希望小伙伴们可以认真阅读以上文字,有利于加深我们的理解,总结一下:

js中的数据类型分为`原始值类型``对象类型``原始值类型`也就是我们刚才所说的`基本数据类型`或者叫`值类型`,具体不一一列出来,请看上文
    
    `对象类型「引用数据类型」`分为:
        `标准普通对象`:object
        `标准特殊对象`ArrayRegExpDateMathError……
        `非标准特殊对象`NumberStringBoolean……
        `可调用/执行对象「函数」`function

typeof的使用

让我们看看typeof的具体使用方法:

'原始值类型'
typeof 1  // "number"
typeof ""  // "string"
typeof true  // "boolean"
typeof null  // "object"
typeof a  // a未被声明定义,因此为"undefined"
typeof Symbol(1)  // "symbol" 
typeof 12n  // "bigint"

'对象类型'
typeof function(){}  // "function"
typeof 除可调用/执行对象(函数)的其他对象类型  // "object"

总结一下typeof的注意点

1、typeof首先返回的是一个字符串(双引号""包括);

2、原始数据类型中nulltypeof返回的是"object"

3、对象类型中,除了可调用/执行对象的typeof值为"function",其他的都无法通过typeof进行区分,都为"object"

4、typeof一个未被声明的变量,返回一个"undefined"

typeof的底层原理

12.5.6.1 Runtime Semantics: Evaluation
UnaryExpression : typeof UnaryExpression
Let val be the result of evaluating UnaryExpression.
If Type(val) is Reference, then
If IsUnresolvableReference(val) is true, return “undefined”.
Let val be GetValue(val).
ReturnIfAbrupt(val).
Return a String according to Table 35.

UnaryExpression: UnaryExpression的类型
设val为对UnaryExpression求值的结果。
如果类型(val)是引用,则
如果IsUnresolvableReference(val)为真,则返回“undefined”。
让val为GetValue(val)。
ReturnIfAbrupt (val)。
根据下表返回一个字符串。

image.pngGetValue(val)中,计算机底层又进行了处理,它将所有的值都以64位二进制进行了存储,而typeof就是按照计算机底层存储的二进制进行检测,它具有效率高的这么一个优点。

检测规则

typeof会以二进制数开头的某几位进行检测,规则如下:

-   000 对象
-   1 整数
-   010 浮点数
-   100 字符串
-   110 布尔
-   000000… null(全都为0)
-   -2^30 undefined
-   ……

其中:

1、整数浮点数他们的检测结果返回的都是"number"数据类型;

2、如果检测到该值二进制开头是以"000"开头,并且内部实现了call()方法,则该值为一个"function"类型。

总结

以上就是有关计算机typeof检测数据类型的底层原理,这时候可能又有小伙伴问了,那如何去检测对象类型中的除可调用对象的其他三种对象类型呢?后续还会对这一块进行讲解,请大家持续关注哦。码字不易,感谢大家的阅读。转载请附上原文链接,谢谢啦^_^。