PageSourceSearch

https://ansonznl.github.io/assets/js/v-deb9aae6.3c4af3d5.js

js ansonznl.github.io collected 2026-10-03 08:40:53 UTC 10,667 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[9095],{4680:(a,n,s)=>{s.r(n),s.d(n,{data:()=>p});const p={key:"v-deb9aae6",path:"/articles/JavaScript/JavaScript%E7%9A%84%E9%A2%84%E7%BC%96%E8%AF%91%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90.html",title:"JavaScript 的预编译过程分析",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"一、JavaScript 概念",slug:"一、javascript-概念",children:[]},{level:2,title:"二、JavaScript 语言特点",slug:"二、javascript-语言特点",children:[{level:3,title:"2.1 单线程",slug:"_2-1-单线程",children:[]},{level:3,title:"2.2 解释型语言",slug:"_2-2-解释型语言",children:[]}]},{level:2,title:"三、 JavaScript 执行过程",slug:"三、-javascript-执行过程",children:[{level:3,title:"3.1 语法分析",slug:"_3-1-语法分析",children:[]},{level:3,title:"3.2 预编译",slug:"_3-2-预编译",children:[]},{level:3,title:"3.3 解释执行",slug:"_3-3-解释执行",children:[]}]},{level:2,title:"总结",slug:"总结",children:[]}],filePathRelative:"articles/JavaScript/JavaScript的预编译过程分析.md",git:{}}},931:(a,n,s)=>{s.r(n),s.d(n,{default:()=>e});const p=(0,s(6252).uE)('<h1 id="javascript-的预编译过程分析" tabindex="-1"><a class="header-anchor" href="#javascript-的预编译过程分析" aria-hidden="true">#</a> JavaScript 的预编译过程分析</h1><h2 id="一、javascript-概念" tabindex="-1"><a class="header-anchor" href="#一、javascript-概念" aria-hidden="true">#</a> 一、JavaScript 概念</h2><p>JavaScript ( JS ) 是一个单线程、解释型的编程语言。</p><h2 id="二、javascript-语言特点" tabindex="-1"><a class="header-anchor" href="#二、javascript-语言特点" aria-hidden="true">#</a> 二、JavaScript 语言特点</h2><h3 id="_2-1-单线程" tabindex="-1"><a class="header-anchor" href="#_2-1-单线程" aria-hidden="true">#</a> 2.1 单线程</h3><p>JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。</p><h3 id="_2-2-解释型语言" tabindex="-1"><a class="header-anchor" href="#_2-2-解释型语言" aria-hidden="true">#</a> 2.2 解释型语言</h3><p>自上而下,解释一行,执行一行;不会通篇编译为一个文件再执行。</p><h2 id="三、-javascript-执行过程" tabindex="-1"><a class="header-anchor" href="#三、-javascript-执行过程" aria-hidden="true">#</a> 三、 JavaScript 执行过程</h2><h3 id="_3-1-语法分析" tabindex="-1"><a class="header-anchor" href="#_3-1-语法分析" aria-hidden="true">#</a> 3.1 语法分析</h3><p>顾名思义 就是检查一遍 js 代码内有没有出现语法错误(比如少些个分号,多写个括号等);语法分析期间不会执行代码</p><h3 id="_3-2-预编译" tabindex="-1"><a class="header-anchor" href="#_3-2-预编译" aria-hidden="true">#</a> 3.2 预编译</h3><p><strong>预编译发生在函数执行的前一刻</strong><strong>全局下:</strong> 全局的变量声明和函数声明则会存放在全局对象内(Global Object 简称 GO,它是 window 的一部分,你可以直接把他理解成 window 对象)中 <strong>函数体内:</strong> 预编译会提前把函数里的变量声明和函数声明依据规则存放在该活动对象内(Activation Object,简称 AO),</p><p>预编译简单理解就是在内存中开辟一些空间,存放一些变量与函数 。</p><p>预编译大致可分为 4 步:</p><ol><li>创建 AO(GO)对象</li><li>找形参和变量声明,将形参和变量名作为 AO(GO)属性名,值为 undefined</li><li>将实参值和形参统一</li><li>在函数体里面找函数声明,值赋予函数体。</li></ol><p>所以如果遇到下面这种情况,当函数声明和变量声明名称相同时:</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>\n<span class="token keyword">function</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>编译后的代码其实是:</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">var</span> a<span class="token punctuation">;</span>\n<span class="token keyword">function</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>\na <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>\n</code></pre><div class="line-numbers"><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></div></div><p>所以最后输出的是:</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br></div></div><h4 id="预编译小节" tabindex="-1"><a class="header-anchor" href="#预编译小节" aria-hidden="true">
1#</a> 预编译小节</h4><p><strong>预编译两个小规则</strong></p><ol><li>函数声明整体提升—(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)</li><li>变量 声明提升—(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是 undefined),只有在解释执行阶段才会进行变量初始化,匿名函数不参与预编译。</li></ol><p><strong>预编译前奏</strong></p><ol><li>imply global 即任何变量,如果未经声明就赋值,则此变量就位全局变量所有(全局域就是 window) 。</li><li>一切声明的全局变量,全是 window 的属性。</li></ol><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token operator">&lt;</span>script<span class="token operator">&gt;</span><span class="token keyword">var</span> a<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//2&lt;/script&gt;</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br></div></div><h3 id="_3-3-解释执行" tabindex="-1"><a class="header-anchor" href="#_3-3-解释执行" aria-hidden="true">#</a> 3.3 解释执行</h3><p>预编译完毕之后,JavaScript 脚本开始执行,执行顺序按照从上到下的顺序执行。</p><h2 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h2><p><strong>JavaScript 执行顺序</strong></p><ol><li>语法分析</li><li>预编译<br> 2.1. 创建 AO(GO)对象<br> 2.2. 找形参和变量声明,将形参和变量名作为 AO(GO)属性名,值为 undefined<br> 2.3. 将实参值和形参统一<br> 2.4. 在函数体里面找函数声明,值赋予函数体。</li><li>解释执行</li></ol><p>练习:</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token parameter">a</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  a <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>\n  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token keyword">var</span> b <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>\n  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span>\n<span class="token function">a</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>\n</code></pre><div class="line-numbers"><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></div></div><p>你可以先试想一下结果,然后复制代码到控制台去验证你的答案是否正确。</p>',36),e={render:function(a,n){return p}}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.