JS---原始类型为什么能调用方法

79 阅读1分钟

参考地址:原始类型的方法


假如,有这样一段代码,将字符串转换为大写:

                  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>