From fe061782d66ec87e2f9880d8b933cf65e13a079f Mon Sep 17 00:00:00 2001
From: Yangshun <tay.yang.shun@gmail.com>
Date: Thu, 3 Apr 2025 19:52:27 +0800
Subject: [PATCH] i18n: translate 2 qns

---
 .../en-US.langnostic.json                     |  57 +++++
 .../zh-CN.mdx                                 | 112 +++++++---
 .../en-US.langnostic.json                     |  96 ++++++++
 questions/describe-event-bubbling/zh-CN.mdx   | 209 ++++++++++++++++--
 4 files changed, 428 insertions(+), 46 deletions(-)
 create mode 100644 questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/en-US.langnostic.json
 create mode 100644 questions/describe-event-bubbling/en-US.langnostic.json

diff --git a/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/en-US.langnostic.json b/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/en-US.langnostic.json
new file mode 100644
index 0000000..3109d8d
--- /dev/null
+++ b/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/en-US.langnostic.json
@@ -0,0 +1,57 @@
+{
+  "frontmatter": {
+    "title": "5ba0d4da",
+    "subtitle": "4d47ead"
+  },
+  "content": {
+    "source": {
+      "locale": "en-US",
+      "hashes": [
+        "77da26a5",
+        "4010c03b",
+        "b7950cbe",
+        "2a7816d0",
+        "678d2642",
+        "7ac0c956",
+        "4e1ff55c",
+        "d3b7242",
+        "a203d791",
+        "8550812",
+        "54dee6b3",
+        "a6f52eea",
+        "cb0ae1a8",
+        "e5dcf6c0",
+        "839f0ebb",
+        "d8fa43b8",
+        "30eae852",
+        "be10dd6f",
+        "1f4770e5",
+        "6232231"
+      ]
+    },
+    "targets": {
+      "zh-CN": [
+        "77da26a5",
+        "4010c03b",
+        "b7950cbe",
+        "2a7816d0",
+        "678d2642",
+        "7ac0c956",
+        "4e1ff55c",
+        "d3b7242",
+        "a203d791",
+        "8550812",
+        "54dee6b3",
+        "a6f52eea",
+        "cb0ae1a8",
+        "e5dcf6c0",
+        "839f0ebb",
+        "d8fa43b8",
+        "30eae852",
+        "be10dd6f",
+        "1f4770e5",
+        "6232231"
+      ]
+    }
+  }
+}
diff --git a/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/zh-CN.mdx b/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/zh-CN.mdx
index c6ba1df..2b657a9 100644
--- a/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/zh-CN.mdx
+++ b/questions/can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions/zh-CN.mdx
@@ -1,50 +1,102 @@
 ---
-title: 您可以为新箭头函数语法提供一个用例吗？
-subtitle: 这个新语法与其他函数有什么不同？
+title: 箭头 => 函数语法有什么用例？
+subtitle: 这种新语法与其他函数有何不同？
 ---
 
-`=>` 函数语法，也被称为 "箭头函数"，是在 ECMAScript 6（ES6）中引入的 JavaScript 功能。它提供了一种更简洁的编写函数的方式，并且在 `this` 的行为方面与传统函数表达式有一些不同。下面通过一个简单的用例来说明它的实用性：
+## TL;DR
 
-## 用例：筛选数组
+箭头函数为用 JavaScript 编写函数提供了一种简洁的语法。它们对于在方法和回调中维护 `this` 上下文特别有用。例如，在事件处理程序或像 `map` 这样的数组方法中，箭头函数可以简化代码并避免 `this` 绑定问题。
 
-假设你有一个包含数字的数组，你想筛选出所有小于 10 的数字。你可以使用传统的函数语法和新的箭头函数语法来实现这一目标，如下所示：
+```js live
+const numbers = [1, 2, 3];
+const doubled = numbers.map((n) => n * 2);
+console.log(doubled); // [2, 4, 6]
+```
 
-### 传统函数语法
+***
 
-```js
-const numbers = [1, 5, 10, 15, 20];
-const filteredNumbers = numbers.filter(function (number) {
-  return number >= 10;
-});
+## 新箭头 => 函数语法的用例
+
+### 简化语法
+
+箭头函数提供了一种更简洁的编写函数的方式。这对于短函数或回调特别有用。
 
-console.log(filteredNumbers); // 输出: [10, 15, 20]
+```js live
+// Traditional function
+const add = function (a, b) {
+  return a + b;
+};
+
+// Arrow function
+const anotherAdd = (a, b) => a + b;
+
+console.log(add(2, 3)); // Output: 5
+console.log(anotherAdd(2, 3)); // Output: 5
 ```
 
-### 箭头函数语法
+### 词法 `this` 绑定
+
+箭头函数没有自己的 `this` 上下文。相反，它们从周围的范围继承 `this`。这在 `this` 上下文可能很棘手的方法和回调中特别有用。
 
-```js
-const numbers = [1, 5, 10, 15, 20];
-const filteredNumbers = numbers.filter((number) => number >= 10);
+```js live
+function Timer() {
+  this.seconds = 0;
+  this.increment = () => {
+    this.seconds++; // 'this.seconds' is inherited from the outer scope
+    console.log(this.seconds);
+  };
+}
 
-console.log(filteredNumbers); // 输出: [10, 15, 20]
+const timer = new Timer();
+timer.increment(); // 1
+timer.increment(); // 2
 ```
 
-## 箭头函数的优点
+在上面的例子中，在 `setInterval` 中使用传统函数需要额外的步骤来维护正确的 `this` 上下文。
 
-1. **简洁性**：箭头函数更加简洁，使你的代码更短且易于阅读。
-1. **`this` 行为**：箭头函数没有自己的 `this`。相反，它们继承自它们在定义时的父级作用域中的 `this`。这在处理回调并希望保留 `this` 上下文的情况下特别有用。
-1. **隐式返回**：如果函数体只包含一个表达式，箭头函数允许省略 `return` 关键字和花括号。
+### 在数组方法中使用箭头函数
 
-## 何时使用箭头函数
+箭头函数通常用于 `map`、`filter` 和 `reduce` 等数组方法中，以获得更简洁、更易读的代码。
 
-- 当你需要一个快速的、单行的函数时。
-- 在回调函数中，当你想要保留 `this` 的词法作用域时。
-- 在使用 `map`、`filter`、`reduce` 等高阶函数时。
+```js live
+const numbers = [1, 2, 3, 4, 5];
 
-## 何时不要使用箭头函数
+// Traditional function
+const doubledTraditional = numbers.map(function (n) {
+  return n * 2;
+});
+
+// Arrow function
+const doubled = numbers.map((n) => n * 2);
+
+console.log(doubled); // [2, 4, 6, 8, 10]
+```
+
+### 事件处理程序
+
+箭头函数可用于事件处理程序，以维护类或对象的 `this` 上下文。
+
+```js live
+class Button {
+  constructor() {
+    this.count = 0;
+    this.button = document.createElement('button');
+    this.button.innerText = 'Click me';
+    this.button.addEventListener('click', () => {
+      this.count++;
+      console.log('count:', this.count);
+    });
+    document.body.appendChild(this.button);
+  }
+}
+
+const myButton = new Button();
+myButton.button.click(); // count: 1
+myButton.button.click(); // count: 2
+```
 
-- **对象方法**：箭头函数没有自己的 `this` 上下文，在对象方法中可能会导致意外行为。
-- **作为构造函数**：箭头函数不能作为构造函数使用，如果使用 `new` 关键字会引发错误。
-- **当你需要使用函数提升**：与传统的函数声明不同，箭头函数不会提升。
+## 延伸阅读
 
-箭头函数是 JavaScript 的一个强大补充，简化了函数语法，并解决了传统函数中 `this` 关键字的一些常见问题。它们在现代 JavaScript 开发模式中特别有用。
+* [MDN Web Docs: Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
+* [JavaScript.info: Arrow functions revisited](https://javascript.info/arrow-functions)
+* [Eloquent JavaScript: Functions](https://eloquentjavascript.net/03_functions.html)
diff --git a/questions/describe-event-bubbling/en-US.langnostic.json b/questions/describe-event-bubbling/en-US.langnostic.json
new file mode 100644
index 0000000..c1c657a
--- /dev/null
+++ b/questions/describe-event-bubbling/en-US.langnostic.json
@@ -0,0 +1,96 @@
+{
+  "frontmatter": {
+    "title": "e76fac09"
+  },
+  "content": {
+    "source": {
+      "locale": "en-US",
+      "hashes": [
+        "77da26a5",
+        "1cdd9fe1",
+        "940c1a5e",
+        "2a7816d0",
+        "8f8a1b0c",
+        "72e7e3c9",
+        "63bf7424",
+        "a71258b2",
+        "7009889d",
+        "7c18e66f",
+        "ae34ee20",
+        "e04e0f0f",
+        "d186cc4a",
+        "a517a702",
+        "9e538dcd",
+        "3818abba",
+        "47a90b06",
+        "10d6cb7a",
+        "1f177e65",
+        "d7a0aa2",
+        "68b07c90",
+        "e2a961ac",
+        "c81ac723",
+        "965b6bd7",
+        "b0d83e27",
+        "a8ff50ea",
+        "3625d327",
+        "ac7b2126",
+        "92f262c4",
+        "b37f85fb",
+        "3c0717ad",
+        "26112098",
+        "2dfccf1a",
+        "5a641ee3",
+        "647830d7",
+        "758c287c",
+        "ad083d17",
+        "da4b57bd",
+        "1f4770e5",
+        "d00fe19e"
+      ]
+    },
+    "targets": {
+      "zh-CN": [
+        "77da26a5",
+        "1cdd9fe1",
+        "940c1a5e",
+        "2a7816d0",
+        "8f8a1b0c",
+        "72e7e3c9",
+        "63bf7424",
+        "a71258b2",
+        "7009889d",
+        "7c18e66f",
+        "ae34ee20",
+        "e04e0f0f",
+        "d186cc4a",
+        "a517a702",
+        "9e538dcd",
+        "3818abba",
+        "47a90b06",
+        "10d6cb7a",
+        "1f177e65",
+        "d7a0aa2",
+        "68b07c90",
+        "e2a961ac",
+        "c81ac723",
+        "965b6bd7",
+        "b0d83e27",
+        "a8ff50ea",
+        "3625d327",
+        "ac7b2126",
+        "92f262c4",
+        "b37f85fb",
+        "3c0717ad",
+        "26112098",
+        "2dfccf1a",
+        "5a641ee3",
+        "647830d7",
+        "758c287c",
+        "ad083d17",
+        "da4b57bd",
+        "1f4770e5",
+        "d00fe19e"
+      ]
+    }
+  }
+}
diff --git a/questions/describe-event-bubbling/zh-CN.mdx b/questions/describe-event-bubbling/zh-CN.mdx
index 720b389..af3b4bc 100644
--- a/questions/describe-event-bubbling/zh-CN.mdx
+++ b/questions/describe-event-bubbling/zh-CN.mdx
@@ -1,45 +1,222 @@
 ---
-title: 描述事件冒泡过程
+title: 描述 JavaScript 和浏览器的事件冒泡
 ---
 
-事件冒泡是 DOM（文档对象模型）中的一种传播机制，其中事件，如点击或键盘事件，首先在启动事件的目标元素上触发，然后向上（冒泡）通过 DOM 树传播到文档的根部。
+## TL;DR
+
+事件冒泡是一种 DOM 事件传播机制，其中一个事件（例如点击）从目标元素开始，冒泡到文档的根。这允许祖先元素也响应事件。
+
+事件冒泡对于事件委托至关重要，其中单个事件处理程序管理多个子元素的事件，从而提高性能和代码简洁性。虽然方便，但未能正确管理事件传播可能导致意外行为，例如多个处理程序为单个事件触发。
+
+---
+
+## 什么是事件冒泡？
+
+事件冒泡是 DOM（文档对象模型）中的一种传播机制，其中一个事件（例如点击或键盘事件）首先在触发事件的目标元素上触发，然后向上（冒泡）通过 DOM 树传播到文档的根。
+
+**注意**：甚至在事件冒泡阶段发生之前是 [事件捕获](/questions/quiz/describe-event-capturing) 阶段，该阶段与冒泡相反，事件从文档根向下到目标元素。
 
 ## 冒泡阶段
 
-在冒泡阶段期间，事件从目标元素开始，并通过其在 DOM 层次结构中的祖先向上冒泡。这意味着附加到目标元素及其祖先的事件处理程序都有可能接收并响应事件。
+在冒泡阶段，事件从目标元素开始，通过其在 DOM 层次结构中的祖先元素冒泡。这意味着附加到目标元素及其祖先的事件处理程序都可能接收并响应事件。
 
-以下是使用现代 ES6 语法演示事件冒泡的示例：
+这里有一个使用现代 ES6 语法的示例，用于演示事件冒泡：
 
-```js
+```js live
 // HTML:
 // <div id="parent">
-//   <button id="child">点击我！</button>
+//   <button id="child">Click me!</button>
 // </div>
+const parentDiv = document.createElement('div');
+parentDiv.id = 'parent';
+const button = document.createElement('button');
+button.id = 'child';
+parentDiv.appendChild(button);
+document.body.appendChild(parentDiv);
 
 const parent = document.getElementById('parent');
 const child = document.getElementById('child');
 
 parent.addEventListener('click', () => {
-  console.log('单击了父元素');
+  console.log('Parent element clicked');
 });
 
 child.addEventListener('click', () => {
-  console.log('单击了子元素');
+  console.log('Child element clicked');
 });
+
+// Simulate clicking the button:
+child.click();
 ```
 
-当单击 "点击我！" 按钮时，由于事件冒泡，子元素和父元素的事件处理程序都将被触发。
+当您点击“Click me!”按钮时，由于事件冒泡，子元素和父元素的事件处理程序都将被触发。
+
+## 停止冒泡
 
-## 阻止传播
+可以使用 `stopPropagation()` 方法在冒泡阶段停止事件冒泡。如果事件处理程序调用 `stopPropagation()`，它会阻止事件进一步冒泡到 DOM 树中，确保仅执行层次结构中该点之前的元素的处理程序。
 
-在冒泡阶段，可以使用 `stopPropagation()` 方法停止事件传播。如果事件处理程序调用 `stopPropagation()`，它将阻止事件继续向上冒泡到 DOM 树，确保只有位于层次结构中的元素的处理程序被执行。
+```js live
+// HTML:
+// <div id="parent">
+//   <button id="child">Click me!</button>
+// </div>
+const parentDiv = document.createElement('div');
+parentDiv.id = 'parent';
+const button = document.createElement('button');
+button.id = 'child';
+parentDiv.appendChild(button);
+document.body.appendChild(parentDiv);
+
+const parent = document.getElementById('parent');
+const child = document.getElementById('child');
+
+parent.addEventListener('click', () => {
+  console.log('Parent element clicked');
+});
+
+child.addEventListener('click', (event) => {
+  console.log('Child element clicked');
+  event.stopPropagation(); // Stops propagation to parent
+});
+
+// Simulate clicking the button:
+child.click();
+```
 
 ## 事件委托
 
-事件冒泡是一种称为 "事件委托" 的技术的基础，其中将单个事件处理程序附加到多个元素的共同祖先，并使用事件委托有效地处理这些元素的事件。当您有大量类似元素，例如项目列表时，希望避免为每个项目附加单独的事件处理程序时，这种方法特别有用。
+事件冒泡是称为 [事件委托](/questions/quiz/describe-event-delegation) 的技术的基础，您将单个事件处理程序附加到多个元素的公共祖先，并使用事件委托来有效地处理这些元素的事件。当您有大量相似的元素（如项目列表）并且希望避免将单独的事件处理程序附加到每个项目时，这特别有用。
+
+```js
+parent.addEventListener('click', (event) => {
+  if (event.target && event.target.id === 'child') {
+    console.log('Child element clicked');
+  }
+});
+```
+
+## 优点
+
+- **更简洁的代码：** 减少事件监听器的数量，提高代码可读性和可维护性。
+- **高效的事件处理：** 通过附加更少的监听器，最大限度地减少性能开销。
+- **灵活性：** 允许处理子元素上发生的事件，而无需直接将监听器附加到它们。
+
+## 陷阱
+
+- **意外的事件处理：** 请注意，父元素可能会无意中捕获子元素发生的事件。使用 `event.target` 来识别触发事件的特定元素。
+- **事件顺序：** 事件以特定顺序冒泡。如果多个父元素有事件监听器，它们的执行顺序取决于 DOM 层次结构。
+- **过度委托：** 虽然将事件委托给公共祖先是有效的，但在 DOM 树中附加一个过高的监听器可能会捕获意外的事件。
+
+## 用例
+
+以下是一些使用事件冒泡编写更好代码的实用方法。
+
+### 使用事件委托减少代码
+
+想象一下，您有一个产品列表，其中包含许多项目，每个项目都有一个“立即购买”按钮。 传统上，您可以将单独的点击事件监听器附加到每个按钮：
+
+```js
+// HTML:
+// <ul id="product-list">
+//   <li><button id="item1-buy">立即购买</button></li>
+//   <li><button id="item2-buy">立即购买</button></li>
+// </ul>
+
+const item1Buy = document.getElementById('item1-buy');
+const item2Buy = document.getElementById('item2-buy');
+
+item1Buy.addEventListener('click', handleBuyClick);
+item2Buy.addEventListener('click', handleBuyClick);
+
+// ... 对每个项目重复 ...
+
+function handleBuyClick(event) {
+  console.log('点击了项目的购买按钮：', event.target.id);
+}
+```
+
+随着项目数量的增加，这种方法变得很麻烦。 以下是事件冒泡如何简化事情的方法：
+
+```js
+// HTML:
+// <ul id="product-list">
+//   <li><button id="item1-buy">立即购买</button></li>
+//   <li><button id="item2-buy">立即购买</button></li>
+// </ul>
+
+const productList = document.getElementById('product-list');
+
+productList.addEventListener('click', handleBuyClick);
+
+function handleBuyClick(event) {
+  // 检查点击的元素是否是列表中的一个按钮
+  if (event.target.tagName.toLowerCase() === 'button') {
+    console.log('点击了项目的购买按钮：', event.target.textContent);
+  }
+}
+```
+
+通过将监听器附加到父元素 (`productList`) 并在处理程序中检查被点击的元素 (`event.target`)，您可以用更少的代码实现相同的功能。 当项目是动态的时，这种方法可以很好地扩展，因为当项目列表发生变化时，不需要添加或删除新的事件处理程序。
+
+### 下拉菜单
+
+考虑一个下拉菜单，点击菜单元素（父元素）的任何地方都应该关闭它。使用事件冒泡，您可以使用一个监听器来实现这一点：
+
+```js
+// HTML:
+// <div id="dropdown">
+//   <button>打开菜单</button>
+//   <ul>
+//     <li>项目 1</li>
+//     <li>项目 2</li>
+//   </ul>
+// </div>
+
+const dropdown = document.getElementById('dropdown');
+
+dropdown.addEventListener('click', handleDropdownClick);
+
+function handleDropdownClick(event) {
+  // 如果在按钮外部单击，则关闭下拉菜单
+  if (event.target !== dropdown.querySelector('button')) {
+    console.log('下拉菜单已关闭');
+    // 隐藏下拉菜单内容的逻辑
+  }
+}
+```
+
+在这里，点击事件从被点击的元素（按钮或列表项）冒泡到 `dropdown` 元素。 处理程序检查被点击的元素是否不是 `<button>`，并相应地关闭菜单。
+
+### 手风琴菜单
+
+想象一个手风琴菜单，点击一个部分标题（父级）会展开或折叠其下方的部分内容（子级）。 事件冒泡使这变得简单：
+
+```js
+// HTML:
+// <div class="accordion">
+//   <div class="header">第 1 节</div>
+//   <div class="content">第 1 节的内容</div>
+//   <div class="header">第 2 节</div>
+//   <div class="content">第 2 节的内容</div>
+// </div>
+
+const accordion = document.querySelector('.accordion');
+
+accordion.addEventListener('click', handleAccordionClick);
+
+function handleAccordionClick(event) {
+  // 检查点击的元素是否是标题
+  if (event.target.classList.contains('header')) {
+    const content = event.target.nextElementSibling;
+    content.classList.toggle('active'); // 切换内容的显示
+  }
+}
+```
+
+通过将监听器附加到 `accordion` 元素，单击任何标题都会触发该事件。 处理程序检查被点击的元素是否是标题，并切换相应内容部分的可见性。
 
-## 参考资料
+## 延伸阅读
 
-- [MDN Web Docs 上的事件冒泡](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
-- [JavaScript.info - 冒泡和捕获](https://javascript.info/bubbling-and-capturing)
-- [W3C DOM Level 3 事件规范](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
+- [MDN Web Docs on Event Bubbling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
+- [JavaScript.info - Bubbling and Capturing](https://javascript.info/bubbling-and-capturing)
+- [W3C DOM Level 3 Events Specification](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
