--- title: 什么是 JavaScript? slug: Learn/JavaScript/First_steps/What_is_JavaScript tags: - API - JavaScript - 初学者 - 核心 - 浏览器 translation_of: Learn/JavaScript/First_steps/What_is_JavaScript --- <div dir="ltr">{{LearnSidebar}}</div> <div dir="ltr">{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</div> <p class="summary" dir="ltr">欢迎来到 MDN 的 JavaScript 初学者课程!本节将在一定高度俯瞰 JavaScript,回答一些诸如“它是什么?”和“它能做什么?”的问题 。并使你熟悉 JavaScript 的用途。</p> <table class="learn-box standard-table" dir="ltr"> <tbody> <tr> <th scope="row">预备知识:</th> <td>计算机基础知识,初步理解 HTML 和 CSS 。</td> </tr> <tr> <th scope="row">目标:</th> <td>初步了解 JavaScript,包括一些概念、用途、嵌入网站的方法。</td> </tr> </tbody> </table> <h2 dir="ltr" id="广义的定义">广义的定义</h2> <p dir="ltr">JavaScript 是一种脚本,一门编程语言,它可以在网页上实现复杂的功能,网页展现给你的不再是简单的静态信息,而是实时的内容更新,交互式的地图,2D/3D 动画,滚动播放的视频等等。JavaScript 怎能缺席。它是标准 Web 技术蛋糕的第三层,其中 <a href="/en-US/docs/Learn/HTML">HTML </a>和 <a href="/en-US/docs/Learn/CSS">CSS </a>我们已经在学习中心的其他部分进行了详细的讲解。</p> <p><img alt="" dir="ltr" src="https://mdn.mozillademos.org/files/13502/cake.png" style="display: block; height: 291px; margin: 0px auto; width: 300px;"></p> <ul dir="ltr"> <li>{{glossary("HTML")}}是一种标记语言,用来结构化我们的网页内容并赋予内容含义,例如定义段落、标题和数据表,或在页面中嵌入图片和视频。</li> <li>{{glossary("CSS")}} 是一种样式规则语言,可将样式应用于 HTML 内容, 例如设置背景颜色和字体,在多个列中布局内容。</li> <li>{{glossary("JavaScript")}} 是一种脚本语言,可以用来创建动态更新的内容,控制多媒体,制作图像动画,还有很多。(好吧,虽然它不是万能的,但可以通过简短的代码来实现神奇的功能。)</li> </ul> <p dir="ltr">这三层依次建立,秩序井然。以文本标签(text label)的简单示例。首先用 HTML 将文本标记起来,从而赋予它结构和目的:</p> <pre class="brush: html notranslate"><p>玩家1:小明</p></pre> <p dir="ltr">玩家1:小明</p> <p dir="ltr">然后我们可以为它加一点 CSS 让它更好看:</p> <pre class="brush: css notranslate">p { font-family: sans-serif, '黑体'; letter-spacing: 1px; text-transform: uppercase; text-align: center; border: 2px solid rgba(0, 0, 200, 0.6); background: rgba(0, 0, 200, 0.3); color: rgba(0, 0, 200, 0.6); box-shadow: 1px 1px 2px rgba(0, 0, 200, 0.4); border-radius: 10px; padding: 3px 10px; display: inline-block; cursor: pointer; }</pre> <div class="hidden" dir="ltr"> <h6 id="Beautiful_name_label">Beautiful name label</h6> <pre class="brush: html notranslate"><!DOCTYPE html> <html><head><style> p { font-family: sans-serif, '黑体'; letter-spacing: 1px; text-transform: uppercase; text-align: center; border: 2px solid rgba(0, 0, 200, 0.6); background: rgba(0, 0, 200, 0.3); color: rgba(0, 0, 200, 0.6); box-shadow: 1px 1px 2px rgba(0, 0, 200, 0.4); border-radius: 10px; padding: 3px 10px; display: inline-block; cursor: pointer; } </style></head> <body> <p>玩家1:小明</p> </body></html></pre> </div> <p dir="ltr">{{ EmbedLiveSample('Beautiful_name_label', '100%', 80, "", "", "hide-codepen-jsfiddle") }}</p> <p dir="ltr">最后,我们可以再加上一些 JavaScript 来实现动态行为:</p> <pre class="brush: js notranslate">const para = document.querySelector('p'); para.addEventListener('click', updateName); function updateName() { let name = prompt('输入一个新的名字:'); para.textContent = '玩家1:' + name; } </pre> <div class="hidden" dir="ltr"> <h6 id="Customizable_name_label">Customizable name label</h6> <pre class="brush: html notranslate"><!DOCTYPE html> <html><head><style> p { font-family: sans-serif, '黑体'; letter-spacing: 1px; text-transform: uppercase; text-align: center; border: 2px solid rgba(0,0,200,0.6); background: rgba(0,0,200,0.3); color: rgba(0,0,200,0.6); box-shadow: 1px 1px 2px rgba(0,0,200,0.4); border-radius: 10px; padding: 3px 10px; display: inline-block; cursor: pointer; } </style></head> <body> <p>玩家1:小明</p> <script> const para = document.querySelector('p'); para.addEventListener('click', updateName); function updateName() { const name = prompt('输入一个新的名字:'); para.textContent = '玩家1:' + name; } </script> </body></html></pre> </div> <p dir="ltr">{{ EmbedLiveSample('Customizable_name_label', '100%', 80, "", "", "hide-codepen-jsfiddle") }}</p> <p dir="ltr">尝试点击最后一个版本的文本标签,观察会发生什么(也可在 GitHub 上查看这个 demo 的 <a class="external external-icon" href="https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-label.html">源代码</a> 或 <a class="external external-icon" href="https://roy-tian.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/javascript-label.html">在线运行</a>。)</p> <p dir="ltr">JavaScript 能做的远不止这些。让我们来仔细探索。</p> <h2 dir="ltr" id="它到底可以做什么?">它到底可以做什么?</h2> <p dir="ltr">客户端(client-side)JavaScript 语言的核心包含一些普遍的编程特性,以让你可以做到如下的事情:</p> <ul dir="ltr"> <li>在变量中储存有用的值。比如上文的示例中,我们请求客户输入一个新名字,然后将其储存到 <code>name</code> 变量中。</li> <li>操作一段文本(在编程中称为“字符串”(string))。上文的示例中,我们取字符串 "玩家1:",然后把它和 <code>name</code> 变量连结起来,创造出完整的文本标签,比如:"玩家1:小明"。</li> <li>运行代码以响应网页中发生的特定事件。上文的示例中,我们用一个 {{Event("click")}} 事件来检测按钮什么时候被点击,然后运行代码更新文本标签。</li> <li>以及更多!</li> </ul> <p dir="ltr">JavaScript 语言核心之上所构建的功能更令人兴奋。<strong>应用程序接口(Application Programming Interfaces</strong>(<strong>API</strong>))将为你的代码提供额外的超能力。</p> <p dir="ltr">API 是已经建立好的一套代码组件,可以让开发者实现原本很难甚至无法实现的程序。就像现成的家具套件之于家居建设,用一些已经切好的木板组装一个书柜,显然比自己设计,寻找合适的木材,裁切至合适的尺寸和形状,找到正确尺寸的螺钉,再组装成书柜要简单得多。</p> <p dir="ltr">API 通常分为两类。</p> <p><img alt="" dir="ltr" src="https://mdn.mozillademos.org/files/13508/browser.png" style="display: block; height: 511px; margin: 0px auto; width: 815px;"></p> <p dir="ltr"><strong>浏览器 API</strong> 内建于 web 浏览器中,它们可以将数据从周边计算机环境中筛选出来,还可以做实用的复杂工作。例如:</p> <ul dir="ltr"> <li>{{domxref("Document_Object_Model","文档对象模型 API(DOM(Document Object Model)API)")}} 能通过创建、移除和修改 HTML,为页面动态应用新样式等手段来操作 HTML 和 CSS。比如当某个页面出现了一个弹窗,或者显示了一些新内容(像上文小 demo 中看到那样),这就是 DOM 在运行。</li> <li>{{domxref("Geolocation","地理位置 API(Geolocation API)")}} 获取地理信息。这就是为什么 <a href="https://www.google.cn/maps">谷歌地图</a> 可以找到你的位置,而且标示在地图上。</li> <li>{{domxref("Canvas_API","画布(Canvas)")}} 和 {{domxref("WebGL_API","WebGL")}} API 可以创建生动的 2D 和 3D 图像。人们正运用这些 web 技术制作令人惊叹的作品。参见 <a href="https://www.chromeexperiments.com/webgl">Chrome Experiments</a> 以及 <a href="http://webglsamples.org/">webglsamples</a>。</li> <li>诸如 {{domxref("HTMLMediaElement")}} 和 {{domxref("WebRTC API", "WebRTC")}} 等 <a href="https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery">影音类 API</a> 让你可以利用多媒体做一些非常有趣的事,比如在网页中直接播放音乐和影片,或用自己的网络摄像头获取录像,然后在其他人的电脑上展示(试用简易版 <a href="http://chrisdavidmills.github.io/snapshot/">截图 demo</a> 以理解这个概念)。</li> </ul> <div class="note" dir="ltr"> <p><strong>注</strong>: 上述很多演示都不能在旧浏览器中运行。推荐你在测试代码时使用诸如 Firefox, Chrome, Edge 或者 Opera 等现代浏览器。当代码即将交付生产环境时(也就是真实的客户即将使用真实的代码时),你还需要深入考虑 <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">跨平台测试</a>。</p> </div> <p dir="ltr"><strong>第三方 API </strong>并没有默认嵌入浏览器中,一般要从网上取得它们的代码和信息。比如:</p> <ul dir="ltr"> <li><a href="https://dev.twitter.com/overview/documentation">Twitter API</a>、<a href="https://open.weibo.com/">新浪微博 API</a> 可以在网站上展示最新推文之类。</li> <li><a href="https://developers.google.com/maps/">谷歌地图 API</a>、<a href="https://lbs.amap.com/">高德地图 API</a> 可以在网站嵌入定制的地图等等。</li> </ul> <div class="note" dir="ltr"> <p><strong>注</strong>:这些 API 较为高级,我们的课程中不会涉及,更多信息请参考:<a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Client-side_web_APIs">客户端 web API 模块</a>.</p> </div> <p dir="ltr">先稳住!你看到的只是冰山一角。你不可能学一天 JavaScript 就能构建下一个Facebook, 谷歌地图, 或者 Instagram。敬请「牢记初心,砥砺前行」。</p> <h2 dir="ltr" id="JavaScript_在页面上做了什么?">JavaScript 在页面上做了什么?</h2> <p dir="ltr">现在我们实实在在的学习一些代码,与此同时,探索 JavaScript 运行时背后发生的事情。</p> <p dir="ltr">让我们简单回顾一下,浏览器在读取一个网页时都发生什么(<a href="/zh-CN/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_does_CSS_actually_work">CSS 如何工作</a> 一文中首次谈及)。浏览器在读取一个网页时,代码(HTML, CSS 和 JavaScript)将在一个运行环境(浏览器标签页)中得到执行。就像一间工厂,将原材料(代码)加工为一件产品(网页)。</p> <p><img alt="" dir="ltr" src="https://mdn.mozillademos.org/files/13504/execution.png" style="display: block; margin: 0 auto;"></p> <p dir="ltr">在 HTML 和 CSS 集合组装成一个网页后,浏览器的 JavaScript 引擎将执行 JavaScript 代码。这保证了当 JavaScript 开始运行之前,网页的结构和样式已经就位。</p> <p dir="ltr">这样很好,因为JavaScript 最普遍的用处是通过 DOM API(见上文)动态修改 HTML 和 CSS 来更新用户界面 (user interface)。如果 JavaScript 在 HTML 和 CSS 就位之前加载运行,就会引发错误。</p> <h3 dir="ltr" id="浏览器安全">浏览器安全</h3> <p dir="ltr">每个浏览器标签页就是其自身用来运行代码的独立容器(这些容器用专业术语称为“运行环境”)。大多数情况下,每个标签页中的代码完全独立运行,而且一个标签页中的代码不能直接影响另一个标签页(或者另一个网站)中的代码。这是一个好的安全措施,如果不这样,黑客就可以从其他网站盗取信息,等等。</p> <div class="note" dir="ltr"> <p><strong>注</strong>:以安全的方式在不同网站/标签页中传送代码和数据的方法是存在的,但这些技术较为高级,本课程不会涉及。</p> </div> <h3 dir="ltr" id="JavaScript_运行次序">JavaScript 运行次序</h3> <p dir="ltr">当浏览器执行到一段 JavaScript 代码时,通常会按从上往下的顺序执行这段代码。这意味着你需要注意代码书写的顺序。比如,我们回到第一个例子中的 JavaScript 代码:</p> <pre class="brush: js notranslate">const para = document.querySelector('p'); para.addEventListener('click', updateName); function updateName() { let name = prompt('输入一个新的名字:'); para.textContent = '玩家1:' + name; }</pre> <p dir="ltr">这里我们选定一个文本段落(第 1 行),然后给它附上一个事件监听器(第 3 行),使得在它被点击时,<code>updateName()</code> 代码块(code block) (5 – 8 行)便会运行。<code>updateName()</code> (这类可以重复使用的代码块称为“函数”)向用户请求一个新名字,然后把这个名字插入到段落中以更新显示。</p> <p dir="ltr">如果你互换了代码里最初两行的顺序,会导致问题。浏览器<a href="zh-CN/docs/Learn/Discover_browser_developer_tools">开发者控制台</a>将返回一个错误: <code>TypeError: para is undefined</code>。这意味着 <code>para</code> 对象还不存在,所以我们不能为它增添一个事件监听器。</p> <div class="note" dir="ltr"> <p><strong>注</strong>:这是一个很常见的错误,在引用对象之前必须确保该对象已经存在。</p> </div> <h3 dir="ltr" id="解释代码_vs_编译代码">解释代码 vs 编译代码</h3> <p dir="ltr">作为程序员,你或许听说过这两个术语:<strong>解释(</strong><strong>interpret)</strong>和 <strong>编译(compile)</strong>。在解释型语言中,代码自上而下运行,且实时返回运行结果。代码在由浏览器执行前,不需要将其转化为其他形式。代码将直接以文本格式(text form)被接收和处理。</p> <p dir="ltr">相对的,编译型语言需要先将代码转化(编译)成另一种形式才能运行。比如 C/C++ 先被编译成汇编语言,然后才能由计算机运行。程序将以二进制的格式运行,这些二进制内容是由程序源代码产生的。</p> <p dir="ltr">JavaScript 是轻量级解释型语言。浏览器接受到JavaScript代码,并以代码自身的文本格式运行它。技术上,几乎所有 JavaScript 转换器都运用了一种叫做即时编译(just-in-time compiling)的技术;当 JavaScript 源代码被执行时,它会被编译成二进制的格式,使代码运行速度更快。尽管如此,JavaScript 仍然是一门解释型语言,因为编译过程发生在代码运行中,而非之前。</p> <p dir="ltr">两种类型的语言各有优势,这个问题我们暂且不谈。</p> <h3 dir="ltr" id="服务器端代码_vs_客户端代码">服务器端代码 vs 客户端代码</h3> <p dir="ltr">你或许还听说过<strong>服务器端(server-side)</strong>和 <strong>客户端(client-side)</strong>代码这两个术语,尤其是在web开发时。客户端代码是在用户的电脑上运行的代码,在浏览一个网页时,它的客户端代码就会被下载,然后由浏览器来运行并展示。这就是<strong>客户端 JavaScript</strong>。</p> <p dir="ltr">而服务器端代码在服务器上运行,接着运行结果才由浏览器下载并展示出来。流行的服务器端 web 语言包括:PHP、Python、Ruby、ASP.NET 以及...... JavaScript!JavaScript 也可用作服务器端语言,比如现在流行的 Node.js 环境,你可以在我们的 <a href="/zh-CN/docs/Learn/Server-side">动态网页 - 服务器端编程</a> 主题中找到更多关于服务器端 JavaScript 的知识。</p> <h3 dir="ltr" id="动态代码_vs_静态代码">动态代码 vs 静态代码</h3> <p dir="ltr">“<strong>动态</strong>”一词既适用于客户端 JavaScript,又适用于描述服务器端语言。是指通过按需生成新内容来更新 web 页面 / 应用,使得不同环境下显示不同内容。服务器端代码会在服务器上动态生成新内容,例如从数据库中提取信息。而客户端 JavaScript 则在用户端浏览器中动态生成新内容,比如说创建一个新的 HTML 表格,用从服务器请求到的数据填充,然后在网页中向用户展示这个表格。两种情况的意义略有不同,但又有所关联,且两者(服务器端和客户端)经常协同作战。</p> <p dir="ltr">没有动态更新内容的网页叫做“<strong>静态</strong>”页面<strong>,</strong>所显示的内容不会改变。</p> <h2 dir="ltr" id="怎样向页面添加_JavaScript?">怎样向页面添加 JavaScript?</h2> <p dir="ltr">可以像添加 CSS 那样将 JavaScript 添加到 HTML 页面中。CSS 使用 {{htmlelement("link")}} 元素链接外部样式表,使用 {{htmlelement("style")}} 元素向 HTML 嵌入内部样式表,JavaScript 这里只需一个元素——{{htmlelement("script")}}。我们来看看它是怎么工作的。</p> <h3 dir="ltr" id="内部_JavaScript">内部 JavaScript</h3> <ol dir="ltr"> <li>首先,下载示例文件 <a href="https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript.html" id="92a6bf0d0009a65dbe8e2051e58c9e9c-69e65808c197b337a320d1613964f0ea3e3ba5f1" title="apply-javascript.html">apply-javascript.html</a>。放在一个好记的文件夹里。</li> <li>分别在浏览器和文本编辑器中打开这个文件。你会看到这个 HTML 文件创建了一个简单的网页,其中有一个可点击按钮。</li> <li><font face="Open Sans, Arial, sans-serif">然后转到文本编辑器,在 </font><code></head></code> 标签结束前插入以下代码: <pre class="brush: html notranslate"><script> // 在此编写 JavaScript 代码 </script></pre> </li> <li>下面,在 {{htmlelement("script")}} 元素中添加一些 JavaScript 代码,这个页面就能做一些更有趣的事。在“/ /在此编写 JavaScript 代码”一行下方添加以下代码: <pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { function createParagraph() { let para = document.createElement('p'); para.textContent = '你点击了这个按钮!'; document.body.appendChild(para); } const buttons = document.querySelectorAll('button'); for(let i = 0; i < buttons.length ; i++) { buttons[i].addEventListener('click', createParagraph); } });</pre> </li> <li>保存文件并刷新浏览器,然后你会发现,点击按钮文档下方将会添加一个新段落。</li> </ol> <div class="note" dir="ltr"> <p><strong>注</strong>: 如果示例不能正常工作,请依次检查所有步骤,并保证没有纰漏。原始文件是否以 <code>.html</code> 为扩展名保存到本地了?<code></body></code> 标签前是否添加了 {{htmlelement("script")}} 元素?JavaScript 代码输入是否正确 ? <strong>JavaScript 是区分大小写的,而且非常精确,所以你需要准确无误地输入所示的句法,否则可能会出错。</strong></p> </div> <div class="note" dir="ltr"> <p><strong>注</strong>: 你可以在 GitHub 上查看此版本 <a class="external external-icon" href="https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">apply-internal.html</a> (<a class="external external-icon" href="https://roy-tian.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">也可在线查看</a>)。</p> </div> <h3 dir="ltr" id="外部_JavaScript">外部 JavaScript</h3> <p dir="ltr">这很不错,但是能不能把 JavaScript 代码放置在一个外部文件中呢?现在我们来研究一下。</p> <ol dir="ltr"> <li>首先,在刚才的 HTML 文件所在的目录下创建一个名为 <code>script.js</code> 的新文件。请确保扩展名为 <code>.js</code>,只有这样才能被识别为 JavaScript 代码。</li> <li>将 {{htmlelement("script")}} 元素替换为: <pre class="brush: html notranslate"><script src="script.js" async></script></pre> </li> <li>在 <code>script.js</code> 文件中,添加下面的脚本: <pre class="brush: js notranslate"><code class="language-js"><span class="keyword token">function</span> <span class="function token">createParagraph</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> let para <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">createElement</span><span class="punctuation token">(</span><span class="string token">'p'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> para<span class="punctuation token">.</span>textContent <span class="operator token">=</span> <span class="string token">'你点击了这个按钮!'</span><span class="punctuation token">;</span> document<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">appendChild</span><span class="punctuation token">(</span>para<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="punctuation token">}</span></code> const buttons <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelectorAll</span><span class="punctuation token">(</span><span class="string token">'button'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="keyword token">for</span><span class="punctuation token">(let</span> i <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> i <span class="operator token"><</span> buttons<span class="punctuation token">.</span>length <span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> buttons<span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">'click'</span><span class="punctuation token">,</span> createParagraph<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="punctuation token">}</span> </pre> </li> <li>保存并刷新浏览器,你会发现二者完全一样。但是现在我们把 JavaScript 写进了一个外部文件。这样做一般会使代码更加有序,更易于复用,且没有了脚本的混合,HTML 也会更加易读,因此这是个好的习惯。</li> </ol> <div class="note" dir="ltr"> <p><strong>注</strong>:你可以在 GitHub 上查看这个版本 <a class="external external-icon" href="https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">apply-external.html</a> 以及 <a class="external external-icon" href="https://github.com/roy-tian/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/script.js">script.js</a> (<a class="external external-icon" href="https://roy-tian.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">也可在线查看</a>).</p> </div> <h3 dir="ltr" id="内联_JavaScript_处理器">内联 JavaScript 处理器</h3> <p dir="ltr">注意,有时候你会遇到在 HTML 中存在着一丝真实的 JavaScript 代码。它或许看上去像这样:</p> <pre class="brush: js example-bad line-numbers language-js notranslate"><code class="language-js"><span class="keyword token">function</span> <span class="function token">createParagraph</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> const para <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">createElement</span><span class="punctuation token">(</span><span class="string token">'p'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> para<span class="punctuation token">.</span>textContent <span class="operator token">=</span> <span class="string token">'你点击了这个按钮!'</span><span class="punctuation token">;</span> document<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">appendChild</span><span class="punctuation token">(</span>para<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="punctuation token">}</span></code></pre> <pre class="brush: html example-bad notranslate"><button onclick="createParagraph()">点我呀</button></pre> <p dir="ltr">你可以在下面尝试这个版本的 demo。</p> <div class="hidden" dir="ltr"> <h6 id="Inline_JavaScript">Inline JavaScript</h6> <pre class="brush: html notranslate"><code><!DOCTYPE html></code> <code><html lang="zh-CN"> <head> <meta charset="utf-8"> <title>JavaScript 示例</title> <script> </code><code class="language-js"><span class="keyword token">function</span> <span class="function token">createParagraph</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> const para <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">createElement</span><span class="punctuation token">(</span><span class="string token">'p'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> para<span class="punctuation token">.</span>textContent <span class="operator token">=</span> <span class="string token">'你点击了这个按钮!'</span><span class="punctuation token">;</span> document<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">appendChild</span><span class="punctuation token">(</span>para<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="punctuation token"> }</span></code> <code> </script> </head> <body> <button onclick="createParagraph()">点我呀</button> </body> </html></code> </pre> </div> <p dir="ltr">{{ EmbedLiveSample('Inline_JavaScript', '100%', 150, "", "", "hide-codepen-jsfiddle") }}</p> <p dir="ltr">这个 demo 与之前的两个功能完全一致,只是在 {{htmlelement("button")}} 元素中包含了一个内联的 <code>onclick</code> 处理器,使得函数在按钮被按下时运行。</p> <p dir="ltr"><strong>然而请不要这样做。</strong> 这将使 JavaScript 污染到 HTML,而且效率低下。对于每个需要应用 JavaScript 的按钮,你都得手动添加 <code>onclick="createParagraph()"</code> 属性。</p> <p dir="ltr">可以使用纯 JavaScript 结构来通过一个指令选取所有按钮。下文的这段代码即实现了这一目的:</p> <pre class="brush: js notranslate">const buttons = document.querySelectorAll('button'); for(let i = 0; i < buttons.length ; i++) { buttons[i].addEventListener('click', createParagraph); }</pre> <p dir="ltr">这样写乍看去比 <code>onclick</code> 属性要长一些,但是这样写会对页面上所有按钮生效,无论多少个,或添加或删除,完全无需修改 JavaScript 代码。</p> <div class="note" dir="ltr"> <p><strong>注</strong>:请尝试修改 <code>apply-javascript.html</code> 以添加更多按钮。刷新后可发现按下任一按钮时都会创建一个段落。很高效吧。</p> </div> <h3 dir="ltr" id="脚本调用策略">脚本调用策略</h3> <p dir="ltr">要让脚本调用的时机符合预期,需要解决一系列的问题。这里看似简单,实际大有文章。最常见的问题就是:HTML 元素是按其在页面中出现的次序调用的,如果用 JavaScript 来管理页面上的元素(更精确的说法是使用 <a href="/zh-CN/docs/Web/API/Document_Object_Model">文档对象模型</a> DOM),若 JavaScript 加载于欲操作的 HTML 元素之前,则代码将出错。</p> <p dir="ltr">在上文的“内部”、“外部”示例中,JavaScript 调用于文档头处,解析 HTML 文档体之前。这样做是有隐患的,需要使用一些结构来避免错误发生。</p> <p dir="ltr">“内部”示例使用了以下结构:</p> <pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { . . . });</pre> <p dir="ltr">这是一个事件监听器,它监听浏览器的 "<code>DOMContentLoaded</code>" 事件,即 HTML 文档体加载、解释完毕事件。事件触发时将调用 " <code>. . .</code>" 处的代码,从而避免了错误发生(<a href="/zh-CN/docs/Learn/JavaScript/Building_blocks/Events">事件</a> 的概念稍后学习)。</p> <p dir="ltr">“外部”示例中使用了 JavaScript 的一项现代技术(<code>async</code> “异步”属性)来解决这一问题,它告知浏览器在遇到 <code><script></code> 元素时不要中断后续 HTML 内容的加载。</p> <pre class="brush: html notranslate"><script src="script.js" async></script></pre> <p dir="ltr">上述情况下,脚本和 HTML 将一并加载,代码将顺利运行。</p> <div class="blockIndicator note" dir="ltr"> <p><strong>注</strong>:“外部”示例中 <code>async</code> 属性可以解决调用顺序问题,因此无需使用 <code>DOMContentLoaded</code> 事件。而 <code>async</code> 只能用于外部脚本,因此不适用于“内部”示例。</p> </div> <p dir="ltr">解决此问题的旧方法是:把脚本元素放在文档体的底端(<code></body></code> 标签之前,与之相邻),这样脚本就可以在 HTML 解析完毕后加载了。此方案(以及上述的 <code>DOMContentLoaded</code> 方案)的问题是:只有在所有 HTML DOM 加载完成后才开始脚本的加载/解析过程。对于有大量 JavaScript 代码的大型网站,可能会带来显著的性能损耗。这也是 <code>async</code> 属性诞生的初衷。</p> <h4 dir="ltr" id="async_和_defer"><code>async</code> 和 <code>defer</code></h4> <p dir="ltr">上述的脚本阻塞问题实际有两种解决方案 —— <code>async</code> 和 <code>defer</code>。我们来依次讲解。</p> <p dir="ltr">浏览器遇到 <code>async</code> 脚本时不会阻塞页面渲染,而是直接下载然后运行。这样脚本的运行次序就无法控制,只是脚本不会阻止剩余页面的显示。当页面的脚本之间彼此独立,且不依赖于本页面的其它任何脚本时,<code>async</code> 是最理想的选择。</p> <p dir="ltr">比如,如果你的页面要加载以下三个脚本:</p> <pre class="brush: html notranslate"><script async src="js/vendor/jquery.js"></script> <script async src="js/script2.js"></script> <script async src="js/script3.js"></script></pre> <p dir="ltr">三者的调用顺序是不确定的。<code>jquery.js</code> 可能在 <code>script2</code> 和 <code>script3</code> 之前或之后调用,如果这样,后两个脚本中依赖 <code>jquery</code> 的函数将产生错误,因为脚本运行时 <code>jquery</code> 尚未加载。</p> <p dir="ltr">解决这一问题可使用 <code>defer</code> 属性,脚本将按照在页面中出现的顺序加载和运行:</p> <pre class="brush: html notranslate" dir="ltr"><script defer src="js/vendor/jquery.js"></script> <script defer src="js/script2.js"></script> <script defer src="js/script3.js"></script></pre> <p dir="ltr">添加 <code>defer</code> 属性的脚本将按照在页面中出现的顺序加载,因此第二个示例可确保 <code>jquery.js</code> 必定加载于 <code>script2.js</code> 和 <code>script3.js</code> 之前,同时 <code>script2.js</code> 必定加载于 <code>script3.js</code> 之前。</p> <p dir="ltr">脚本调用策略小结:</p> <ul dir="ltr"> <li>如果脚本无需等待页面解析,且无依赖独立运行,那么应使用 <code>async</code>。</li> <li>如果脚本需要等待页面解析,且依赖于其它脚本,调用这些脚本时应使用 <code>defer</code>,将关联的脚本按所需顺序置于 HTML 中。</li> </ul> <h2 dir="ltr" id="注释">注释</h2> <p dir="ltr">就像 HTML 和 CSS,JavaScript 代码中也可以添加注释,浏览器会忽略它们,注释只是为你的同事(还有你,如果半年后再看自己写的代码你会说,这是什么垃圾玩意。)提供关于代码如何工作的指引。注释非常有用,而且应该经常使用,尤其在大型应用中。注释分为两类:</p> <ul dir="ltr"> <li>在双斜杠后添加单行注释,比如: <pre class="brush: js notranslate">// 我是一条注释</pre> </li> <li>在 <code>/*</code> 和 <code>*/</code> 之间添加多行注释,比如: <pre class="brush: js notranslate">/* 我也是 一条注释 */</pre> </li> </ul> <p dir="ltr">比如说,我们可以这样为上一个 demo 添加注释:</p> <pre class="brush: js notranslate">// 函数:创建一个新的段落并添加至 HTML body 底部。 function createParagraph() { let para = document.createElement('p'); para.textContent = '你点了这个按钮!'; document.body.appendChild(para); } /* 1. 取得页面上所有按钮的引用并将它们置于一个数组中。 2. 通过一个循环为每个按钮添加一个点击事件的监听器。 当按钮被点击时,调用 createParagraph() 函数。 */ const buttons = document.querySelectorAll('button'); for (let i = 0; i < buttons.length; i++) { buttons[i].addEventListener('click', createParagraph); }</pre> <h2 dir="ltr" id="小结">小结</h2> <p dir="ltr">恭喜你,迈出了探索 JavaScript 世界的第一步。我们从理论开始,介绍为什么要使用 JavaScript,以及用它能做什么事情。过程中穿插了一些代码示例并讲解了 JavaScript 如何与网站中其他代码适配,等等。</p> <p dir="ltr">现在 JavaScript 或许还有些令人生畏,但不用担心。在课程中我们会循序渐进。下一节将<a href="/zh-CN/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash"> 全力投入实战</a>,让你专注其中,并建立自己的 JavaScript 示例。</p> <p dir="ltr">{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</p> <h2 dir="ltr" id="本章目录">本章目录</h2> <ul dir="ltr"> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/What_is_JavaScript">JavaScript 是什么?</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/A_first_splash">JavaScript 初体验</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/What_went_wrong">查找并解决 JavaScript 代码的错误 </a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Variables">变量:储存所需信息</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Math">数字和运算符:JavaScript 的基本算数</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Strings">字符串:JavaScript 文本的处理</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Useful_string_methods">字符串的一些实用方法</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Arrays">数组</a></li> <li><a href="https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps/Silly_story_generator">课程评估:笑话机</a></li> </ul> <p> <audio class="hidden"></audio> </p>