mirror of
https://github.com/ZiuChen/ZiuChen.github.io.git
synced 2025-08-17 23:19:55 +08:00
40 lines
23 KiB
JavaScript
40 lines
23 KiB
JavaScript
import{_ as s,o as n,c as a,a as l}from"./app.33820b61.js";const o="/assets/Object.prototype.toString.70e8308c.png",d=JSON.parse(`{"title":"","description":"","frontmatter":{},"headers":[{"level":2,"title":"深入JavaScript数据类型","slug":"深入javascript数据类型","link":"#深入javascript数据类型","children":[]},{"level":2,"title":"typeof运算符","slug":"typeof运算符","link":"#typeof运算符","children":[{"level":3,"title":"typeof null === 'object'","slug":"typeof-null-object","link":"#typeof-null-object","children":[]},{"level":3,"title":"关于new操作符","slug":"关于new操作符","link":"#关于new操作符","children":[]},{"level":3,"title":"字符串原始值和字符串对象","slug":"字符串原始值和字符串对象","link":"#字符串原始值和字符串对象","children":[]}]},{"level":2,"title":"包装类型","slug":"包装类型","link":"#包装类型","children":[]},{"level":2,"title":"使用toString检查对象类型","slug":"使用tostring检查对象类型","link":"#使用tostring检查对象类型","children":[{"level":3,"title":"核心原理","slug":"核心原理","link":"#核心原理","children":[]}]}],"relativePath":"article/深入JavaScript数据类型.md","lastUpdated":1676979063000}`),e={name:"article/深入JavaScript数据类型.md"},p=l(`<h2 id="深入javascript数据类型" tabindex="-1">深入JavaScript数据类型 <a class="header-anchor" href="#深入javascript数据类型" aria-hidden="true">#</a></h2><p>JavaScript包含以下几种数据类型:</p><ul><li>Number 数字</li><li>String 字符串</li><li>Boolean 布尔值</li><li>Symbol 符号 (ES6新增)</li><li>Object 对象 <ul><li>Function 函数</li><li>Array 数组</li><li>Date 日期</li><li>RegExp 正则表达式</li><li>...</li></ul></li><li>null 空</li><li>undefined 未定义</li></ul><p>从语言底层值的可变与不可变,可以将JS中的数据分为两种:不可变值(原始类型)和可变值(引用类型)</p><p>除了Object及继承自Object的特殊对象,其他的类型都为<strong>原始类型</strong>。</p><h2 id="typeof运算符" tabindex="-1">typeof运算符 <a class="header-anchor" href="#typeof运算符" aria-hidden="true">#</a></h2><p>除了null,所有<strong>原始类型</strong>都可以通过<code>typeof</code>运算符得到不同的结果</p><p>而null与object通过<code>typeof</code>运算符得到的结果都为<code>'object'</code></p><div class="language-javascript line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 除了 null 其他原始类型的变量都可以通过 typeof 得到其类型</span></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// 而 null 与 object 通过 typeof 运算得到的都是 'object'</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> targets </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span><span style="color:#F78C6C;">18</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Symbol</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">''</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">undefined</span><span style="color:#A6ACCD;">]</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> (</span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> t </span><span style="color:#89DDFF;">of</span><span style="color:#A6ACCD;"> targets) </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">typeof</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">t</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// number string boolean symbol object object undefined</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h3 id="typeof-null-object" tabindex="-1"><code>typeof null === 'object'</code> <a class="header-anchor" href="#typeof-null-object" aria-hidden="true">#</a></h3><p>这里援引MDN的解释:</p><blockquote><p>在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。</p><p>由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。</p></blockquote><h3 id="关于new操作符" tabindex="-1">关于new操作符 <a class="header-anchor" href="#关于new操作符" aria-hidden="true">#</a></h3><p>所有使用 new 操作符调用的构造函数,都将返回非基本类型(object 或 function)</p><ul><li>大多数返回的是一个对象,即 <code>object</code></li><li>而构造函数Function返回的是 <code>function</code></li></ul><div class="language-javascript line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 针对普通构造函数</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> str </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">String</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> num </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Number</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">100</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">typeof</span><span style="color:#A6ACCD;"> str) </span><span style="color:#676E95;font-style:italic;">// 'object'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">typeof</span><span style="color:#A6ACCD;"> num) </span><span style="color:#676E95;font-style:italic;">// 'object'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// 针对 Function 构造函数</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> fun </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Function</span><span style="color:#A6ACCD;">()</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">typeof</span><span style="color:#A6ACCD;"> fun) </span><span style="color:#676E95;font-style:italic;">// 'function'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="字符串原始值和字符串对象" tabindex="-1">字符串原始值和字符串对象 <a class="header-anchor" href="#字符串原始值和字符串对象" aria-hidden="true">#</a></h3><p>typeof 操作符区分 <code>String</code> 对象和原始字符串值:</p><div class="language-javascript line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> s1 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">''</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> s2 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">String</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">''</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> s3 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">String</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">''</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(s1 </span><span style="color:#89DDFF;">instanceof</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// false</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(s2 </span><span style="color:#89DDFF;">instanceof</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// true</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(s3 </span><span style="color:#89DDFF;">instanceof</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">String</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// false</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>通过new操作符创建的是一个对象,它将被添加到原型链上(详见new一个对象时发生了什么)</p><p>而直接调用 String 函数,返回的是一个字符串原始值,本质上 <code>s3</code> 和 <code>s1</code> 是相同的</p><p>而<code>s1</code>变量自创建之初,就是原始类型,没有挂载到原型链上,自然也就无法通过<code>instanceof</code>检查一个对象</p><p>而之所以能够在<code>s1</code>上调用字符串的方法,是因为<strong>包装类型</strong>(见下文)</p><blockquote><p>instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。</p><p>在本例中,instanceof用于检查s1变量的原型链上,是否包含构造函数String的显式原型(String.prototype),即:s1是否由String创建</p></blockquote><h2 id="包装类型" tabindex="-1">包装类型 <a class="header-anchor" href="#包装类型" aria-hidden="true">#</a></h2><p>除了null和undefined,所有<strong>原始类型</strong>都有其相应的<strong>对象包装类型</strong>,例如<code>18</code>的对象包装类型是<code>Number</code>,而<code>'Ziu'</code>的对象包装类是<code>String</code></p><p>这为处理原始值提供可用的方法,例如,<code>Number</code>对象提供了<code>toFixed()</code>这样的方法。</p><p>当我们在原始值上访问属性时,JavaScript会<strong>自动将值包装到相应的包装对象中</strong>,并访问对象上的属性:</p><div class="language-javascript line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">((</span><span style="color:#F78C6C;">18.8</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toFixed</span><span style="color:#A6ACCD;">()) </span><span style="color:#676E95;font-style:italic;">// '19'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toUpperCase</span><span style="color:#A6ACCD;">()) </span><span style="color:#676E95;font-style:italic;">// 'ZIU'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="使用tostring检查对象类型" tabindex="-1">使用toString检查对象类型 <a class="header-anchor" href="#使用tostring检查对象类型" aria-hidden="true">#</a></h2><p>由Object派生的每个特殊对象类型都有 <code>toString</code> 方法,而且他们都被不同程度的改写:</p><div class="language-javascript line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">javascript</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 注意,不应当在null或undefined上调用任何方法,这将抛出错误,因为他们没有对应任何包装类型</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> targets </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span><span style="color:#F78C6C;">18</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Symbol</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">''</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Date</span><span style="color:#A6ACCD;">()]</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#A6ACCD;"> (</span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> t </span><span style="color:#89DDFF;">of</span><span style="color:#A6ACCD;"> targets) </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">t</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toString</span><span style="color:#F07178;">()) </span><span style="color:#676E95;font-style:italic;">// '18' 'Ziu' 'true' 'Symbol()' '[object Object]' Sat Feb 18 2023 20:49:31 GMT+0800 (GMT+08:00)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>这个 <code>toString</code> 方法定义在 Object.prototype 上,被其他特殊对象类型所继承。</p><ul><li>如果我们直接调用 <code>Object.prototype.toString()</code> 那么得到的是 <code>[object Object]</code> 因为这是在Object上调用得到的结果</li><li>如果我们在各自不同的对象上调用 <code>toString</code> ,得到的是不同对象改写后的结果</li></ul><p>因为Object是所有子类的父类,所以任何类型的对象都可以通过this绑定的方式,调用<code>Object.prototype.toString()</code>方法,返回该对象的类型的字符串表示</p><p>这也是大多数情况下判断对象类型的方法:</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">classof</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">target</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#FFCB6B;">Object</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">prototype</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">toString</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">call</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// [object xxx]</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#F07178;">(</span><span style="color:#F78C6C;">8</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">-</span><span style="color:#F78C6C;">1</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#82AAFF;">classof</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)) </span><span style="color:#676E95;font-style:italic;">// Object</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="核心原理" tabindex="-1">核心原理 <a class="header-anchor" href="#核心原理" aria-hidden="true">#</a></h3><p><a href="https://juejin.cn/post/6844903477940846600" target="_blank" rel="noreferrer">深入Object.prototype.toString</a></p><p>参考ECMA6规范文档:<a href="https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-object.prototype.tostring" target="_blank" rel="noreferrer">Object.prototype.toString()</a></p><h4 id="es5标准下-object-prototype-tostring-执行原理" tabindex="-1">ES5标准下 <code>Object.prototype.toString</code> 执行原理 <a class="header-anchor" href="#es5标准下-object-prototype-tostring-执行原理" aria-hidden="true">#</a></h4><ul><li>如果 <code>this</code> 是 <code>undefined</code><ul><li>返回 <code>[object Undefined]</code></li></ul></li><li>如果 <code>this</code> 是 <code>null </code><ul><li>返回 <code>[object Null]</code></li></ul></li><li>令 <code>O</code> 为以 <code>this</code> 作为参数调用 <code>ToObject</code> 的结果</li><li>令 <code>class</code> 为 <code>O</code> 的内部属性 <code>[[Class]]</code> 的值</li><li>返回三个字符串 <code>"[object"</code> <code>class</code> 以及 <code>"]"</code> 拼接而成的字符串。</li></ul><h4 id="es6标准下-object-prototype-tostring-执行原理" tabindex="-1">ES6标准下 <code>Object.prototype.toString</code> 执行原理 <a class="header-anchor" href="#es6标准下-object-prototype-tostring-执行原理" aria-hidden="true">#</a></h4><p><code>Object.prototype.toString()</code>被调用时,会进行如下步骤:</p><p><img src="`+o+'" alt="Object.prototype.toString()"></p><p>在ES6里,之前的内部属性 <code>[[Class]]</code> 不再使用,取而代之的是一系列的 internal slot</p>',46),t=[p];function c(r,i,y,D,A,F){return n(),a("div",null,t)}const b=s(e,[["render",c]]);export{d as __pageData,b as default};
|