当前位置: 首页 > article >正文

JAVASCRIPT 基础 DOM元素,MAP方法,获取输入值

从输入框获取数据的一般写法是:
```javascript
const w = parseFloat(document.getElementById("weight").value);
const h = parseFloat(document.getElementById("height").value);
```
而从弹窗获取数据一般写法是:
```javascript
const w = parseFloat(prompt("输入体重:"));
const h = parseFloat(prompt("输入身高:"));
```

下面是几种常见的浏览器弹窗示例:

1. 只展示信息的“警告弹窗”:  
```html
<!-- HTML 中不需要额外代码,JS 可以直接写:-->
<script>
alert("这是一个只展示信息的弹窗");
</script>
```
它不会让用户输入内容,只是单纯显示文本。

2. 带“确认/取消”的弹窗:  
```javascript
if (confirm("确认要删除吗?")) {
    console.log("用户确认");
} else {
    console.log("用户取消");
}
```
它只显示信息并提供“确定/取消”按钮,没有输入框。

3. 带输入框的弹窗 (prompt):  
```javascript
const name = prompt("请输入你的名字:");
console.log(name);
```
它会自动出现一个能让用户输入文本的对话框,用户点击“确定”后将所输入的内容返回给 name 变量。没有办法在这个对话框里添加自定义标签,它是浏览器原生实现的输入弹窗。

---

## 1. innerHTML 的概念

innerHTML 不是分级的概念,而是一个属性,代表一个 DOM 元素的内部 HTML 内容。它不是"相对的"概念,而是指特定 DOM 元素的所有子内容(以 HTML 字符串形式)。当你访问 `element.innerHTML` 时,你获取的是该元素内部的所有 HTML 代码,不包括元素自身的标签。

## 2. 以给定的 HTML 片段为例

```html
<section>
  <img
    src="dinosaur.png"
    alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
  <p>
    Here we will add a link to the
    <a href="https://www.mozilla.org/">Mozilla homepage</a>
  </p>
</section>
```

对于 `<section>` 元素:

```html
- **innerHTML** 是:
  <img
    src="dinosaur.png"
    alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
  <p>
    Here we will add a link to the
    <a href="https://www.mozilla.org/">Mozilla homepage</a>
  </p>
```

- **outerHTML** 是:
```html
<section>
  <img
    src="dinosaur.png"
    alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." />
  <p>
    Here we will add a link to the
    <a href="https://www.mozilla.org/">Mozilla homepage</a>
  </p>
</section>
```

## 3. innerHTML 与 DOM 节点的关系

innerHTML

 是 DOM 节点的一个属性,提供节点内部 HTML 的字符串表示。而 DOM 节点是文档对象模型中的元素,代表 HTML 文档的结构。

### 代码示例:

```javascript
// 获取 section 元素
const section = document.querySelector('section');

// 查看 DOM 节点本身
console.log("DOM 节点:", section);
// 输出: [object HTMLSectionElement] (浏览器中会显示更详细的对象信息)

// 查看 innerHTML (HTML 字符串)
console.log("innerHTML:", section.innerHTML);
// 输出: 内部的 HTML 内容字符串

// 查看 outerHTML (包含自身的 HTML 字符串)
console.log("outerHTML:", section.outerHTML);
// 输出: 包含自身在内的 HTML 内容字符串

// 查看 DOM 节点的子节点 (实际的 DOM 节点对象数组,而非 HTML 字符串)
console.log("子节点:", section.childNodes);
// 输出: NodeList [img, text, p]

// 修改 innerHTML (会替换所有子内容)
section.innerHTML = "<h1>新内容</h1>";
// 现在 section 只包含一个 h1 元素
```

DOM 节点是对象,而 innerHTML 是一个返回或设置 HTML 字符串的属性。当你修改 innerHTML 时,浏览器会解析这个字符串并创建新的 DOM 节点来替换原有内容。

---

把 <script> 放在 body 底部的策略对内联脚本和外部脚本都有效。当浏览器加载 HTML 时,直到解析到 <script> 标签时才会加载并执行这段脚本;因此,无论脚本代码内联还是通过 src 引入,都能确保在页面的元素加载完毕后再执行脚本。

---

给定一个包含学生成绩的字典数组,使用 map 修改数组,其中包含学生姓名和他们的成绩等级(>=90 为 "A", >=80 为 "B", >=70 为 "C", 其他为 "F")。

const students = [
    { name: 'Alice', score: 92 },
    { name: 'Bob', score: 76 },
    { name: 'Charlie', score: 85 },
    { name: 'Dave', score: 63 }
];
const passingScore = {
    A: 90,
    B: 80,
    C: 70,
    D: 60
}
students = students.map(onestudent => {
    const score=onestudent.score;
;
    for( const attribute in passingScore){
        const threshold = passingScore.attribute;
        if(score>=threshold){
            return onestudent.grade>=threshold? onestudent.grade=`${attribute}` :`${attribute}`
        }
    }
});
console.log(students);

我认为return onestudent.grade>=threshold? onestudent.grade=${attribute} :${attribute} 能保证“不断随着最大能达到的等级来更新,最终只留下最大匹配”

这段代码存在几个严重问题,**无法**实现"不断随着最大能达到的等级来更新,最终留下最大匹配":

1. **属性访问错误**:
   ```javascript
   const threshold = passingScore.attribute;
   ```
   应该用方括号访问:`passingScore[attribute]`,因为attribute是变量

2. **提前返回**:
   ```javascript
   if(score>=threshold){
       return onestudent.grade>=threshold? onestudent.grade=`${attribute}` :`${attribute}`
   }
   ```
   当找到第一个符合条件的阈值时就立即返回,无法比较所有等级

3. **遍历顺序问题**:`for...in`循环的遍历顺序不确定,可能先检查D再检查A

4. **返回值混乱**:
   - 正在返回字符串值而不是学生对象
   - 三元表达式逻辑不明确

// 正确的实现方式
const students = [
    { name: 'Alice', score: 92 },
    { name: 'Bob', score: 76 },
    { name: 'Charlie', score: 85 },
    { name: 'Dave', score: 63 }
];

const gradedStudents = students.map(student => {
    const score = student.score;
    
    if (score >= 90) {
        return { name: student.name, grade: 'A' };
    } else if (score >= 80) {
        return { name: student.name, grade: 'B' };
    } else if (score >= 70) {
        return { name: student.name, grade: 'C' };
    } else {
        return { name: student.name, grade: 'F' };
    }
});

console.log(gradedStudents);

---

# JavaScript map() 方法的参数解释

map()方法接受一个回调函数作为唯一必需的参数。实际语法是:

```javascript
array.map(callback)
```

其中 `callback` 是一个函数,会被应用于数组的每个元素。这个回调函数可以接收三个参数:
1. 当前元素
2. 当前索引(可选)
3. 原数组(可选)

## 两种常见的写法:

### 1. 内联定义函数:
```javascript
students = students.map(function(onestudent) {
    // 这里的代码会应用到每个 student
    return /* 某个值 */;
});
```

### 2. 使用预定义函数:
```javascript
function changeLevel(onestudent) {
    // 处理逻辑
    return /* 某个值 */;
}

students = students.map(changeLevel);
```

## 错误示例(不正确的语法):
```javascript
// 这是错误的!map 不接受两个参数
students = students.map(onestudent, changeLevel);
```

所以 students.map(function(onestudent) {...})是完全正确的语法,其中 `function(onestudent) {...}` 就是传递给 map()的回调函数。在这里,onestudent 是回调函数的参数,代表当前正在处理的数组元素。

在 JavaScript 的 map()函数中,参数是在函数定义时声明的。onestudent不需要在外部预先定义,它是作为回调函数的参数自动创建的。

这个概念可能对初学者来说有点抽象,让我用一个简单的例子来解释:

```javascript
// 普通的函数调用
function greet(person) {
    console.log("Hello, " + person);
}
greet("John"); // person = "John"

// 类似地,map 自动为每个数组元素调用你的函数
students.map(onestudent => {
    // 这里 onestudent 自动等于当前正在处理的数组元素
    // 第一次循环:onestudent = { name: 'Alice', score: 92 }
    // 第二次循环:onestudent = { name: 'Bob', score: 76 }
    // 以此类推...
});
```

map() 方法会自动:
1. 遍历数组中的每个元素
2. 对每个元素调用你提供的函数
3. 将当前元素作为参数传递给函数
4. 收集函数的返回值组成一个新数组

所以 onestudent是在函数参数位置上定义的变量,它会自动接收当前正在处理的学生对象。这是 JavaScript 函数式编程的标准模式,你不需要预先声明这个变量。
---
1. DOM 节点层级判断标准

在 DOM 中,每个 HTML 元素都是一个节点,但节点不仅限于元素。节点类型包括:

- 元素节点(如 `<p>`、`<span>`)
- 文本节点(元素内的文本)
- 注释节点(HTML 注释)
- 属性节点等

2. DOM 节点和 CSS 选择器的对比
- DOM 包含文本节点,CSS 选择器不直接处理文本节点
- CSS 选择器有特殊语法(如 `>`、`+`、`~` 等组合器)

### 比较例子:

```html
<div id="container">
  <p class="intro">Hello <span>world</span></p>
  <p>Another paragraph</p>
</div>
```

**DOM 访问方式:**
```javascript
// 获取元素节点
const container = document.getElementById("container");
const paragraphs = container.getElementsByTagName("p");
const firstPara = paragraphs[0];
const span = firstPara.getElementsByTagName("span")[0];

// 访问子节点(包括文本节点)
console.log(firstPara.childNodes); // [文本节点"Hello ", span元素节点]
```

**对应的 CSS 选择器:**
```css
/* 选择container下的所有p */
#container p { }

/* 选择container下的直接p子元素 */
#container > p { }

/* 选择intro类的p内部的span */
p.intro span { }
```

CSS 选择器聚焦于元素的选择,而 DOM API 更关注节点的操作和遍历,包括文本节点、注释等非元素节点。

# DOM 选择器与节点关系

## 1. `document.querySelectorAll()` 的行为

`document.querySelectorAll()` 会选择文档中所有匹配 CSS 选择器的元素,无论它们在哪个层级,返回一个 NodeList。

### 1.1 对于示例文件中的选择器:

```javascript
// 选择所有 <p> 元素
const allPs = document.querySelectorAll("p");
console.log(allPs); 
// 结果: NodeList(2) [p, p] 
// 包含 box1 中的 "小猪课堂" 和 box2 中的 "box2p1"、"box2p2"

// 选择所有 <div> 元素
const allDivs = document.querySelectorAll("div");
console.log(allDivs);
// 结果: NodeList(2) [div#box1, div#box2]
// 包含两个 div,一个 id 为 box1,一个 id 为 box2
```

### 1.2 只选择 box2 中的第二个 span (hhh2):

```javascript
// 方法1:使用 CSS 选择器
const secondSpan = document.querySelector("#box2 span:nth-child(4)");
// 或
const secondSpan = document.querySelectorAll("#box2 span")[1];
secondSpan.textContent = "iii2";

// 方法2:使用 DOM 遍历
const box2 = document.getElementById("box2");
const spans = box2.getElementsByTagName("span");
spans[1].textContent = "iii2";
```

### 1.3 选择所有 span 元素并修改:

```javascript
// 选择所有 span 元素
const allSpans = document.querySelectorAll("span");

// 遍历并修改每一个
allSpans.forEach(span => {
  span.textContent = "iii2";
});

// 或使用 for 循环
for (let i = 0; i < allSpans.length; i++) {
  allSpans[i].textContent = "iii2";
}
```

## 2. DOM 节点关系与选择方法

针对你的文件,以下是访问各种节点关系的代码示例:

### 子节点 (Child Nodes)

```javascript
// 获取 box1 的所有子节点(包括文本节点和注释)
const box1 = document.getElementById("box1");
const box1Children = box1.childNodes;
console.log(box1Children); 
// NodeList 包含所有子节点,包括文本节点和注释

// 只获取元素子节点(不包括文本节点和注释)
const box1ElementChildren = box1.children;
console.log(box1ElementChildren);
// HTMLCollection 只包含元素节点:p, span, em
```

### 后代节点 (Descendant Nodes)

```javascript
// 获取 body 下所有的 span 元素(后代,不限于直接子元素)
const allBodySpans = document.querySelectorAll("body span");
console.log(allBodySpans);
// NodeList 包含 body 下所有 span,无论层级深度

// 另一种获取特定后代的方式
const spanInBox2 = document.querySelectorAll("#box2 span");
console.log(spanInBox2);
```

### 父节点 (Parent Node)

```javascript
// 获取第一个 p 元素的父节点
const firstP = document.querySelector("p");
const parentOfP = firstP.parentNode;
console.log(parentOfP); // 是 box1 div

// 或者
console.log(firstP.parentElement);
```

### 兄弟节点 (Sibling Nodes)

```javascript
// 获取 box1 中 p 元素的下一个兄弟元素
const pInBox1 = document.querySelector("#box1 p");
const nextSibling = pInBox1.nextElementSibling;
console.log(nextSibling); // 是 span 元素

// 获取 box1 中 em 元素的上一个兄弟元素
const emInBox1 = document.querySelector("#box1 em");
const prevSibling = emInBox1.previousElementSibling;
console.log(prevSibling); // 是 span 元素

// 注意:nextSibling 和 previousSibling 会包含文本节点
// 而 nextElementSibling 和 previousElementSibling 只包含元素节点
```

这些方法允许你在 DOM 树中精确导航,根据节点之间的关系选择特定元素。与 CSS 选择器不同,这些 DOM 属性提供了更细粒度的控制和访问。


http://www.kler.cn/a/598038.html

相关文章:

  • 【设计模式】SOLID 设计原则概述
  • git日常学习
  • prompt工程起步
  • AI基础01-文本数据采集
  • C语言-装饰器模式详解与实践 - LED控制系统
  • 【MySQL】从零开始:掌握MySQL数据库的核心概念(三)
  • 对接OpenAI 4O RealTime实现语音实时翻译
  • 【Json-RPC框架】:Json存储结构,operator[ ]返回的就是对应的value对象
  • nnunet复现第一天
  • 【weixin9006】优购电商小程序的设计与实现
  • 人工智能之数学基础:特征值和特征向量
  • Pytorch深度学习教程_9_nn模块构建神经网络
  • 数据建模流程: 概念模型>>逻辑模型>>物理模型
  • 大数据驱动:UI设计如何更懂用户
  • 数据结构与算法:宽度优先遍历
  • [node] 4 http模块
  • 【C++教程】break语句
  • MOE框架详解与实现
  • hackmyvm-lookup
  • 数组,指针 易混题解析(二)