三剑客的让人迷惑的一些历史遗留问题

该文会不断更新

button和input的一些迷惑之处

让我们敲下面几行代码

1
2
3
<input type="button" value="点击" />
<input type="submit" value="点击" />
<button >点击</button>

有意思的是运行后,呈现的效果完全相同。

form提交应该使用input:submit还是button:submit? - 知乎 (zhihu.com)

  • <button> 元素是一个更灵活的按钮,可以自定义外观和样式(可以包含文本、图像或其他 HTML 元素),并且可以在点击时执行 JavaScript 操作。如果它位于表单中且没有指定 type 属性,则默认为 “submit” 类型,可以提交表单。
  • <input type="button"> 是一个用于执行 JavaScript 操作的按钮,不会自动提交包含它的表单。
  • <input type="submit"> 是一个用于提交表单的按钮,当用户点击它时,将触发表单的提交动作。
  • 旧版本的浏览器可能对 <button> 元素的行为和样式支持不一致。但<button> 元素通常被认为是更语义化的选择

明明getElementsByClassNamequerySelectorAll可以实现一样的功能为什么要弄两个

getElementsByClassName 是一个原生的 DOM 方法,快一些,返回的是一个动态的 HTMLCollection 对象,该对象会随着 DOM 的变化而实时更新。。

querySelectorAll 是在 DOM API 中引入的新方法,返回的是一个静态的 NodeList 对象

  1. 使用 getElementsByClassName 的应用场景:
    • 动态更新的元素集合:如果需要选择的元素集合需要实时更新,例如在用户交互或事件处理程序中动态添加或删除元素时(比如写todolist
    • 仅按类名选择元素:如果您只需要按类名选择元素,并且不需要使用其他选择器(如标签名、ID、属性等),getElementsByClassName 是一个更简洁的选择。
  2. 使用 querySelectorAll 的应用场景:
    • 复杂的选择器需求:如果您需要使用更复杂的选择器,例如使用层级选择器、伪类选择器等来选择元素,querySelectorAll 提供了更灵活的选择器语法,使您能够使用更多种类的选择器。
    • 静态节点列表:如果您需要获取一个静态的节点列表,并且不需要实时更新,querySelectorAll 可以提供更适合的功能。
    • 使用其他选择器:如果您需要按照标签名、ID、属性等其他选择器选择元素,querySelectorAll 提供了更广泛的选择器选项。

如何区分NodelistHtmlCollection

一个例子(可以直接复制后运行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul>
<li class="example"></li>
<li class="example"></li>
<li class="example"></li>
</ul>
</body>
<script>
// 使用querySelectorAll获取NodeList和getElementsByClassName获取HTMLCollection
const nodeList = document.querySelectorAll("li");
const htmlCollection = document.getElementsByClassName("example");

// 访问节点数量
console.log("NodeList length:", nodeList);
console.log("HTMLCollection length:", htmlCollection);
// 动态添加元素
const ul = document.querySelector("ul");
const li = document.createElement("li");
li.textContent = "New Element";
li.className = "example";
ul.appendChild(li);

// 验证差异
console.log("Updated NodeList length:", nodeList.length); // 不会更新,3相当于快照
console.log("Updated HTMLCollection length:", htmlCollection.length); // 实时更新,4
</script>
</html>

这里我就想到,react和vue的状态管理,react的状态管理是静态的,看官网的描述就知道,它提到了快照,vue了解不多,但它是基于MVVM的有双向绑定的特征

setPrototypeOf 与 Object.create区别

这里又涉及到了动静问题,如果你之前理解了它们之间的区别也会很好理解
功能不同:

setPrototypeOf 方法用于直接修改一个对象的原型。它接受两个参数,第一个参数是要修改原型的对象,第二个参数是新的原型对象。这会改变对象的原型链,并且会立即生效。
Object.create 方法用于创建一个新对象,该新对象的原型被设置为传入的参数。它接受一个参数,即新对象的原型对象。它不会直接修改现有对象的原型链,而是创建一个新的对象,并将其原型设置为指定的原型对象。
兼容性差异:

setPrototypeOf 方法是在 ECMAScript 2015 (ES6) 中引入的,因此在一些较旧的浏览器或环境中可能不受支持。
Object.create 方法在较新的浏览器和环境中得到广泛支持,包括现代的主流浏览器和 Node.js。
使用方式不同:

setPrototypeOf 方法需要直接操作现有的对象,通过传递新的原型对象来修改对象的原型。例如:Object.setPrototypeOf(obj, newPrototype)。
Object.create 方法是一个静态方法,用于创建一个新对象并设置其原型。例如:Object.create(proto)。