参考地址:原始类型的方法
假如,有这样一段代码,将字符串转换为大写:
str.toUpperCase(); // 'ABC'" title="" data-bs-original-title="复制" aria-label="复制"></button>
</div>
</div><pre class="javascript hljs language-javascript"><span class="hljs-keyword">let</span> str = <span class="hljs-string">'abc'</span>;
str.<span class="hljs-title function_">toUpperCase</span>(); <span class="hljs-comment">// 'ABC'</span></pre><p>这是一段简单又普通的代码,按说<code>str</code>是字符串类型,它存储的是一个单值,并且是不可变的,它不能像对象那样,可以存储多个属性,像这样:</p><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark far fa-copy rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="let user = {};
user.name = '张三';
user.say = function () {
return '你好';
};
user.name; // 张三
user.say(); // 你好" title="" data-bs-original-title="复制" aria-label="复制"></button>
</div>
</div><pre class="javascript hljs language-javascript"><span class="hljs-keyword">let</span> user = {};
user.<span class="hljs-property">name</span> = <span class="hljs-string">'张三'</span>;
user.<span class="hljs-property">say</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
<span class="hljs-keyword">return</span> <span class="hljs-string">'你好'</span>;
};
user.<span class="hljs-property">name</span>; <span class="hljs-comment">// 张三</span>
user.<span class="hljs-title function_">say</span>(); <span class="hljs-comment">// 你好</span></pre><p>通过代码可以看到,不能给普通类型添加属性</p><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark far fa-copy rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="let user = '';
user.name = '张三';
user.say = function () {
return '你好';
};
user.age; // undefined
user.say(); // user.say is not a function" title="" data-bs-original-title="复制" aria-label="复制"></button>
</div>
</div><pre class="javascript hljs language-javascript"><span class="hljs-keyword">let</span> user = <span class="hljs-string">''</span>;
user.<span class="hljs-property">name</span> = <span class="hljs-string">'张三'</span>;
user.<span class="hljs-property">say</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) {
<span class="hljs-keyword">return</span> <span class="hljs-string">'你好'</span>;
};
user.<span class="hljs-property">age</span>; <span class="hljs-comment">// undefined</span>
user.<span class="hljs-title function_">say</span>(); <span class="hljs-comment">// user.say is not a function</span></pre><p>那么,为什么原始类型(比如字符串)能够调用方法(比如<code>toUpperCase()</code>)呢?其原理是:<strong>为了使方法起作用,创建了提供额外功能的特殊“对象包装器”,使用后即被销毁</strong>。</p><p>“对象包装器”对于每种原始类型都是不同的,它们被称为 <code>String</code>、<code>Number</code>、<code>Boolean</code>、<code>Symbol</code> 和 <code>BigInt</code>。因此,它们提供了不同的方法。</p><p>以之前的代码为例:</p><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark far fa-copy rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="let str = 'abc';
str.toUpperCase(); // 'ABC'" title="" data-bs-original-title="复制" aria-label="复制"></button>
</div>
</div><pre class="javascript hljs language-javascript"><span class="hljs-keyword">let</span> str = <span class="hljs-string">'abc'</span>;
str.<span class="hljs-title function_">toUpperCase</span>(); <span class="hljs-comment">// 'ABC'</span></pre><p>实际发生的情况:</p><ol><li>字符串 <code>str </code>是一个原始值。因此,在访问其属性时,会创建一个包含字符串字面值的特殊对象,并且具有可用的方法,例如 <code>toUpperCase()</code>。</li><li>该方法运行并返回一个新的字符串。</li><li>特殊对象被销毁,只留下原始值 <code>str</code>。</li></ol><p>所以原始类型可以提供方法,但它们依然是轻量级的。</p><p>JavaScript 引擎高度优化了这个过程。它甚至可能跳过创建额外的对象。但是它仍然必须遵守规范,并且表现得好像它创建了一样。</p>