帮女朋友看作业之appendChild的坑

今天女朋友让我帮她看一下她的 web development 的课程作业,题目是这样的:

  • a button "Add emoji"
  • Whenever the user clicks the button "Add emoji", one more emoji will be added to the webpage:
  • when user clicks "Add emoji" for the first time, display one star emoji;
  • if the user clicks "Add emoji" again, display two emojis: a star and a smiling face;
  • if the user clicks "Add emoji" again, display two emojis: a star and a smiling face, and your name after them;
  • if the user clicks "Add emoji" again, on the first line display two emojis: a star and a smiling
    face, and your name, and then another line with a star emoji;
  • if the user clicks "Add emoji" again, on the first line display two emojis: a star and a smiling
    face, and your name, and then another line with two emojis: a star and a smiling face;
  • if the user clicks "Add emoji" again, display two lines (with the same content) of a star emoji, a smiling face emoji, and your name;
  • and the pattern keeps going like this.

虽然咱秋招唯唯诺诺 ,但这作业不得重拳出击给女朋友见识下咱的实力! 实现完就是下面这个很简单的效果:

如果你学生时代经常被同学问问题会发现,把正确的答案告诉她很容易,但她非想知道她错在哪里,这可能就很麻烦了;就好像大佬直接把我的代码推翻重写,远比帮我 debug 要快得多一样。

只见她掏出了如下代码跟我说:"我照着 GPT 给的代码瞎鼓捣,突然就实现了, appendChild 不是把将一个节点附加到指定父节点的子节点列表的屁股后头吗?这代码的效果不应该是balabala..."

代码:

html 复制代码
<body>
        <button onclick="addEmoji()">Add emoji</button>
        <div id="emojiContainer"></div>

        <script>
            let clickCount = 0;
            let newElement;
            function addEmoji() {
                clickCount++;
                let emojiContainer = document.getElementById('emojiContainer');
                
                if (clickCount % 3 === 1) {
                    newElement = document.createElement('p');
                    newElement.textContent = '⭐';
                } else if (clickCount % 3 === 2) {
                    newElement.textContent += ' 😀';
                } else {
                    newElement.textContent += ' Shaowei Li';
                    emojiContainer.appendChild(newElement);
                }

                
                if (clickCount % 3 !== 0) {
                    emojiContainer.appendChild(newElement);
                }
            }
        </script>
    </body>

她认为这段代码的效果应该是:

嘿,您还别说,乍一看好像真是这么回事。那到底是什么导致了三次点击中, newElement 中的内容没有被依次添加到父节点的最后呢?老实说我也忘了,实习用框架不用操作DOM,秋招八股文也没背到过这块。

于是乎我借口上厕所,在马桶上偷偷掏出手机打开Node.appendChild

Node.appendChild() 方法将一个节点附加到指定父节点的子节点列表的末尾处。如果将被插入的节点已经存在于当前文档的文档树中,那么 appendChild() 只会将它从原先的位置移动到新的位置(不需要事先移除要移动的节点)。

"咳咳,这个问题其实很简单,(将上面的文档内容背诵了一遍),你这里 newElement = document.createElement('p') 在每一行开始的时候都将 newElement 设置成了一个新的节点,而在没有离开这一行时, newElement 指向的是同一个节点,即被插入节点已经存在于文档树中了。Node.appendChild() 会将它移动到新位置,对这里来说就是仍在这一行;而 document.createElement() 返回的是一个新的节点,Node.appendChild() 会将它作为新的子节点插入末尾,故而每一次 clickCount % 3 === 1 才会开启新的一行。"

"......"

"懂了不?(我牛不牛,还不夸我?)"

"这么麻烦,不看了,反正走产品不用懂这个"

"......(感情你搁这抽查我知识点呢)"

相关推荐
子兮曰5 小时前
async/await高级模式:async迭代器、错误边界与并发控制
前端·javascript·github
恋猫de小郭5 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
GIS之路7 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒8 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol9 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉9 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau9 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生9 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼9 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范
明君879979 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter