该文会不断更新
1. button和input的一些迷惑之处
让我们敲下面几行代码
<input type="button" value="点击" />
<input type="submit" value="点击" />
<button >点击</button>
有意思的是运行后,呈现的效果完全相同。
<button>
元素是一个更灵活的按钮,可以自定义外观和样式(可以包含文本、图像或其他 HTML 元素),并且可以在点击时执行 JavaScript 操作。如果它位于表单中且没有指定type
属性,则默认为 “submit” 类型,可以提交表单。<input type="button">
是一个用于执行 JavaScript 操作的按钮,不会自动提交包含它的表单。<input type="submit">
是一个用于提交表单的按钮,当用户点击它时,将触发表单的提交动作。- 旧版本的浏览器可能对
<button>
元素的行为和样式支持不一致。但<button>
元素通常被认为是更语义化的选择
2. 明明getElementsByClassName
和querySelectorAll
可以实现一样的功能为什么要弄两个
getElementsByClassName
是一个原生的 DOM 方法,快一些,返回的是一个动态的 HTMLCollection
对象,该对象会随着 DOM 的变化而实时更新。。
querySelectorAll
是在 DOM API 中引入的新方法,返回的是一个静态的 NodeList
对象
- 使用
getElementsByClassName
的应用场景:- 动态更新的元素集合:如果需要选择的元素集合需要实时更新,例如在用户交互或事件处理程序中动态添加或删除元素时(比如写
todolist
) - 仅按类名选择元素:如果您只需要按类名选择元素,并且不需要使用其他选择器(如标签名、ID、属性等),
getElementsByClassName
是一个更简洁的选择。
- 动态更新的元素集合:如果需要选择的元素集合需要实时更新,例如在用户交互或事件处理程序中动态添加或删除元素时(比如写
- 使用
querySelectorAll
的应用场景:- 复杂的选择器需求:如果您需要使用更复杂的选择器,例如使用层级选择器、伪类选择器等来选择元素,
querySelectorAll
提供了更灵活的选择器语法,使您能够使用更多种类的选择器。 - 静态节点列表:如果您需要获取一个静态的节点列表,并且不需要实时更新,
querySelectorAll
可以提供更适合的功能。 - 使用其他选择器:如果您需要按照标签名、ID、属性等其他选择器选择元素,
querySelectorAll
提供了更广泛的选择器选项。
- 复杂的选择器需求:如果您需要使用更复杂的选择器,例如使用层级选择器、伪类选择器等来选择元素,
3. 如何区分Nodelist
和HtmlCollection
一个例子(可以直接复制后运行)
<!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>
4. 函数为什么是把原型传给对象,而不是本身传给对象?或者问为什么老是遇见构造函数里有原型,而原型里面又有构造函数?(23/12/8更新)
演示案例
function Person(name, age) { this.name = name; this.age = age; } console.log(Person.prototype.constructor === Person); // true
答:函数本身就是一种数据类型,它有自己的任务。它来当构造函数相当于就是为了建立一个原型和对象的桥梁,相当于它生产了一个
类
(不严谨),然后把这个类
交给了新的实例。这也就解释了为什么构造函数的原型里面还要加一个构造函数,因为这个构造函数是给新生成的对象用的。
5.setPrototypeOf 与 Object.create区别(23/12/8)
这里又涉及到了动静问题,如果你之前理解了它们之间的区别也会很好理解
功能不同:
setPrototypeOf 方法用于直接修改一个对象的原型。]
Object.create 方法用于创建一个新对象,该新对象的原型被设置为传入的参数。
兼容性差异:(感觉可以忽略)
setPrototypeOf 方法是在 ECMAScript 2015 (ES6) 中引入的,因此在一些较旧的浏览器或环境中可能不受支持。
Object.create 方法在较新的浏览器和环境中得到广泛支持,包括现代的主流浏览器和 Node.js。
使用方式不同:
setPrototypeOf 方法需要直接操作现有的对象,通过传递新的原型对象来修改对象的原型。例如:Object.setPrototypeOf(obj, newPrototype)。
Object.create 方法是一个静态方法,用于创建一个新对象并设置其原型。例如:Object.create(proto)。
性能方面:
直接操作对象会快一些。