先将节点都变成DOM节点对象

    <script>
        // 开始编写 JavaScript 代码
        // 设置一个数字随机在1-100之间
        let randomNumber = Math.floor(Math.random() * 100) + 1;
        // 创建DOM节点对象 guesses
        const guesses = document.querySelector('.guesses');
        // lastResult
        const lastResult = document.querySelector('.lastResult');
        // lowOrHi
        const lowOrHi = document.querySelector('.lowOrHi');
        const guessSubmit = document.querySelector('.guessSubmit');
        const guessField = document.querySelector('.guessField');
        let guessCount = 1;
        let resetButton;
    </script>

这段代码设置了存储数据的变量和常量以供程序使用。变量本质上是值(例如数字或字符串)的容器。 你可以使用关键字 let (旧代码中使用 var)和一个名字来创建变量(请参阅 let 和 var 之间的区别)。常量用于存储不希望更改的数据,用关键字 const 创建,本例中用常量来保存对界面元素的引用。界面元素的文字可能会改变,但引用是不变的。

可以使用等号(=)和一个值来为变量赋值。

在我们的示例中:

首先用Math的floor方法中的random 生成一个0-100的随机数,并赋值给第一个变量

接下来的三个常量均存储着一个引用, 分别指向HTML结果段落中的某个元素, 用于在代码后面段落中插值

<p class="guesses"></p>
<p class="lastResult"></p>
<p class="lowOrHi"></p>
  • 接下来的两个常量存储对表单文本输入和提交按钮的引用,并用于控制以后提交猜测:
  • <label for="guessField">请猜数:</label>
    <input type="text" id="guessField" class="guessField">
    <input type="submit" value="确定" class="guessSubmit">
    
  • 倒数第二个变量存储一个计数器并初始化为 1(用于跟踪玩家猜测的次数),最后一个变量存储对重置按钮的引用,这个按钮尚不存在(但稍后就有了)
  • 函数(Function)

    下面,在之前的代码中添加以下内容:

    function checkGuess() {
      alert('我是一个占位符');
    

    函数是可复用的代码块,可以一次编写,反复运行,从而节省了大量的重复代码。它们真的很有用。定义函数的方法很多,但现在我们先集中考虑当前这个简单的方式。 这里我们使用关键字 function 、一个函数名、一对小括号定义了一个函数。 随后是一对花括号({})。花括号内部是调用函数时要运行的所有代码。

    要运行一个函数代码时,可以输入函数名加一对小括号。

    让我们尝试一下。保存你的代码并刷新浏览器页面 。然后进入
    开发者工具 JavaScript 控制台,并输入以下代码:

    checkGuess();
    

    在按下 Return/Enter 之后,你应该会看到一个告警窗口,显示 "我是一个占位符";我们在代码中定义了一个函数,当我们调用它时,函数创建了一个告警窗口。

    运算符(Operator)

    条件语句(Conditional)

    回到我们的 checkGuess() 函数,我们希望它不仅能够给出一个占位符消息,同时还能检查玩家是否猜对,并做出适当的反应。我想这并不难吧。

    现在,将当前的 checkGuess() 函数替换为此版本:

     <script>
            // 开始编写 JavaScript 代码
            // 设置一个数字随机在1-100之间
            let randomNumber = Math.floor(Math.random() * 100) + 1;
            // 创建DOM节点对象 guesses
            const guesses = document.querySelector('.guesses');
            // lastResult
            const lastResult = document.querySelector('.lastResult');
            // lowOrHi
            const lowOrHi = document.querySelector('.lowOrHi');
            const guessSubmit = document.querySelector('.guessSubmit');
            const guessField = document.querySelector('.guessField');
            let guessCount = 1;
            let resetButton;
            function checkGuess() {
                // 输入框中得到的值传给userGuess, 使用Number方法确保是一个数字
                let userGuess = Number(guessField.value);
                // 次数为1
                if (guessCount === 1) {
                    guesses.textContent = '上次猜的数: ';
                // 将用户guess存入 guesses的textContent
                guesses.textContent += userGuess + ' ';
                if (userGuess === randomNumber) {
                    lastResult.textContent = '恭喜你! 答对了';
                    lastResult.style.background = 'green';
                    lowOrHi.textContent = '';
                    setGameOver();
                    // 如果不相等 切 次数为10 弹出GG
                } else if (guessCount === 10) {
                    lastResult.textContent = '!!! GAME OVER!!!'
                    setGameOver();
                    // 如果不相等 且次数不为10 
                } else {
                    lastResult.textContent = '你猜错了!';
                    lastResult.style.backgroundColor = 'red';
                    if (userGuess < randomNumber) {
                        lowOrHi.textContent = '你猜低了!';
                    } else if (userGuess > randomNumber) {
                        lowOrHi.textContent = '你猜高了!';
                guessCount++;
                guessField.value = '';
                guessField.focus();
        </script>
    

    如果是, 我们让 guesses 段落的文本内容等于“上次猜的数:”。如果不是就不用了。

  • 第 6 行将当前 userGuess 值附加到 guesses 段落的末尾,并加上一个空格,以使每两个猜测值之间有一个空格。
  • 下一个代码块中(8 - 24 行)做了几个检查:
  • 第一个 if(){ } 检查用户的猜测是否等于在代码顶端设置的 randomNumber 值。如果是,则玩家猜对了,游戏胜利,我们将向玩家显示一个漂亮的绿色的祝贺信息,并清除“高了 / 低了”信息框的内容,调用 setGameOver() 方法。
  • 紧接着是一个 else if(){ } 结构。它会检查这个回合是否是玩家的最后一个回合。如果是,程序将做与前一个程序块相同的事情,只是这次它显示的是 Game Over 而不是祝贺消息。
  • 最后的一个块是 else { },前两个比较都不返回 true 时(也就是玩家尚未猜对,但是还有机会)才会执行这里的代码。在这个情况下,我们会告诉玩家他们猜错了,并执行另一个条件测试,判断并告诉玩家猜测的数字是高了还是低了。
  • 函数最后三行(26 - 28 行)是为下次猜测值提交做准备的。我们把 guessCount 变量的值加 1,以使玩家消耗一次机会 (++ 是自增操作符,为自身加 1),然后我们把表单中文本域的值清空,重新聚焦于此,准备下一轮游戏。
  • 事件(Event)

    现在,我们有一个实现比较不错的 checkGuess() 函数了,但它现在什么事情也做不了,因为我们还没有调用它。 理想中,我们希望在点击“确定”按钮时调用它,为此,我们需要使用事件。 事件就是浏览器中发生的事儿,比如点击按钮、加载页面、播放视频,等等,我们可以通过调用代码来响应事件。 侦听事件发生的结构称为事件监听器(Event Listener),响应事件触发而运行的代码块被称为事件处理器(Event Handler)

    checkGuess() 函数后添加以下代码:

    guessSubmit.addEventListener('click', checkGuess);
    

    这里为 guessSubmit 按钮添加了一个事件监听器。addEventListener() 方法包含两个可输入值(称为“参数”(argument)),监听事件的类型(本例中为“click”),和当事件发生时我们想要执行的代码(本例中为 checkGuess() 函数)。注意,addEventListener() 中作为参数的函数名不加括号。

    现在,保存代码并刷新页面,示例应该能够工作了,但还不够完善。 现在唯一的问题是,如果玩家猜对或游戏次数用完,游戏将出错,因为我们尚未定义游戏结束时应运行的setGameOver() 函数。 现在,让我们补全所缺代码,并完善示例功能。

    checkGuess() 函数后添加以下代码:

    guessSubmit.addEventListener('click', checkGuess);
    

    这里为 guessSubmit 按钮添加了一个事件监听器。addEventListener() 方法包含两个可输入值(称为“参数”(argument)),监听事件的类型(本例中为“click”),和当事件发生时我们想要执行的代码(本例中为 checkGuess() 函数)。注意,addEventListener() 中作为参数的函数名不加括号。

    现在,保存代码并刷新页面,示例应该能够工作了,但还不够完善。 现在唯一的问题是,如果玩家猜对或游戏次数用完,游戏将出错,因为我们尚未定义游戏结束时应运行的setGameOver() 函数。 现在,让我们补全所缺代码,并完善示例功能。

    补全游戏功能

    在代码最后添加一个 setGameOver() 函数,然后我们一起来看看它

            function setGameOver() {
                // 禁用表单文本输入和按钮
                guessField.disabled = true;
                guessSubmit.disabled = true;
                // 创建一个新的button 
                resetButton = document.createElement('button');
                // 设置他的文本为开始新游戏
                resetButton.textContent = '开始新游戏';
                // 将他加到body的最下面
                document.body.appendChild(resetButton);
                // 设置一个监听时间 点击后运行resetGame函数
                resetButton.addEventListener('click', resetGame);
    
  • 前两行通过将 disable 属性设置为 true 来禁用表单文本输入和按钮。 这样做是必须的,否则用户就可以在游戏结束后提交更多的猜测,游戏的规则将遭到破坏。
  • 接下来的三行创建一个新的 `` 元素,设置它的文本为“开始新游戏”,并把它添加到当前 HTML 的底部。
  • 最后一行在新按钮上设置了一个事件监听器,当它被点击时,一个名为 resetGame() 的函数被将被调用。
  • 现在我们需要定义 resetGame() 这个函数,依然放到代码底部:

    function resetGame() {
                // 将次数重新设置为1
                guessCount = 1;
                // 选中所有的信息
                const resetParas = document.querySelectorAll('.resultParas p');
                // 清除所有信息段落
                for (let i = 0; i < resetParas.length; i++) {
                    // 删除当前的p的值
                    resetParas[i].textContent = '';
                // 删除重置按钮
                resetButton.parentNode.removeChild(resetButton);
                guessField.disabled = false;
                guessSubmit.disabled = false;
                // 启用表单元素 清空文本域
                guessField.value = '';
                // 聚焦于此 主播内接受新猜测的数字
                guessField.focus();
                lastResult.style.backgroundColor = 'white';
                // 生成一个新的随机数 这样就可以猜测新的数字了!
                randomNumber = Math.floor(Math.random() * 100) + 1;
    

    这段较长的代码将游戏中的一切重置为初始状态,然后玩家就可以开始新一轮的游戏了。此段代码:

  • guessCount 重置为 1。
  • 清除所有信息段落。
  • 删除重置按钮。
  • 启用表单元素,清空文本域并聚焦于此,准备接受新猜测的数字。
  • 删除 lastResult 段落的背景颜色。
  • 生成一个新的随机数,这样就可以猜测新的数字了!
  • 此刻一个能功能完善的(简易版)游戏就完成了。恭喜!

    我们现在来讨论下其他很重要的代码功能,你可能已经看到过,但是你可能没有意识到这一点。

    循环(Loop)

    上面代码中有一部分需要我们仔细研读,那就是 for 循环。 循环是一个非常重要的编程概念,它让你能够重复运行一段代码,直到满足某个条件为止。

    首先,请再次转到 浏览器开发工具 JavaScript 控制台 然后输入以下内容:

    for (let i = 1; i < 21; i++) { console.log(i); }
    
  • 起始值:本例中我们从 1 开始计数,但其他任意数字也可以。 i也可以用任何你喜欢的名字替换,但一般约定用 i,因为它很短,且易于记忆。
  • 退出条件:这里我们指定 i < 21,直到i不再小于 21 前循环将继续。当 i 达到 21 时,循环将退出。
  • 增加器:我们指定 i++,意思是向 i 加 1。i 值的每次变动都会引发循环的执行,直到 i 值等于 21(如前文所讲)。为简化问题,在本例中,我们使用console.log()在控制台打印出每次迭代时变量 i 的值。
  • 现在让我们来观察猜数字游戏中的循环 —— resetGame() 函数中可以找到以下内容:

    let resetParas = document.querySelectorAll('.resultParas p');
    for (let i = 0 ; i < resetParas.length ; i++) {
      resetParas[i].textContent = '';
    

    这段代码通过 querySelectorAll() 方法创建了一个包含 <div class="resultParas"> 内所有段落的变量,然后通过循环迭代,删除每个段落的文本内容。

    浅谈对象(Object)

    在讨论前最后再改进一波。 在 let resetButton(脚本顶端部分)下方添加下面一行内容,然后保存文件:

    guessField.focus();
    

    这一行通过 focus() 方法让光标在页面加载完毕时自动放置于 `` 输入框内,这意味着玩家可以马上开始第一次猜测,而无需点击输入框。 这只是一个小的改进,却提高了可用性——为使用户能投入游戏提供一个良好的视觉线索。

    深入分析一下。JavaScript 中一切都是对象。对象是存储在单个分组中的相关功能的集合。可以创建自己的对象,但这是较高阶的知识,我们今后才会谈及。现在,仅需简要讨论浏览器内置的对象,它们已经能够做许多有用的事情。

    在本示例的特定情况下,我们首先创建一个 guessField 常量来存储对 HTML 中的文本输入表单域的引用,在文档顶部的声明区域中可以找到以下行:

    const guessField = document.querySelector('.guessField');
    

    使用 document 对象的 querySelector() 方法可以获得这个引用。querySelector() 需要一个信息——用一个 CSS选择器 可以选中需要引用的元素。

    因为 guessField 现在包含一个指向元素的引用,它现在就能够访问一系列的属性(存储于对象内部的基础变量,其中一些的值无法改变)和方法(存储在对象内部的基础函数)。focus()`` 元素可用方法之一,因此我们可以使用这行代码将光标聚焦于此文本框上︰

    操作浏览器对象

    浏览器对象如何使用呢,下面我们来小试牛刀。

    首先在浏览器中打开你的程序。

    接下来打开 浏览器开发者工具, 并且切换到 JavaScript 控制台的标签页。

    输入 guessField ,控制台将会显示此变量包含一个 `` 元素。同时控制台还能自动补全运行环境中对象的名字,包括你的变量!

    现在输入下面的代码:

    guessField.value = 'Hello';
    
    value
    

    属性表示当前文本区域中输入的值。 在输入这条指令后,你将看到文本域区中的文本被我们修改了!

    现在试试输入 guesses 然后回车。控制台会显示一个包含 `` 元素的变量。

    现在试试输入下面这一行:

    guesses.value
    

    浏览器会返回

    undefined
    

    ,因为段落中并不存在

    value
    

    为了改变段落中的文本内容, 你需要用

    textContent

    属性来代替

    value
    

    。试试这个:

    guesses.textContent = '我的段落在哪里?';
    

    下面是一些有趣的东西。 尝试依次输入下面几行:

    guesses.style.backgroundColor = 'yellow';
    guesses.style.fontSize = '200%';
    guesses.style.padding = '10px';
    guesses.style.boxShadow = '3px 3px 6px black';
    

    页面上的每个元素都有一个 style 属性,它本身包含一个对象,其属性包含应用于该元素的所有内联 CSS 样式。 让我们可以使用 JavaScript 在元素上动态设置新的 CSS 样式。

    大功告成...