JavaScript面试题看这一篇就够了,简单全面一发入魂(持续更新 step2)

本文探讨了JavaScript中动态添加div元素导致的死循环问题及其解决方案,强调了使用innerHTML的性能问题及改进方法,并介绍了事件委托的概念和优势,展示了如何通过事件委托解决按钮过多的问题,从而提高代码效率和内存利用率。此外,还讨论了防止表单二次提交的策略,以确保用户体验和数据安全性。
摘要由CSDN通过智能技术生成

一、如何解决循环中动态添加div,造成的死循环问题?

表达式①:

let divs = document.getElementsByTagName("div");
for(let i = 0;i<divs.length;++i){
	let div = document.createElement("div");
	document.body.appendChild(div);
}

表达式②:

let divs = document.getElementsByTagName("div");
for(let i = 0,len=divs.length;i<len;++i){
	let div = document.createElement("div");
	document.body.appendChild(div);
}

表达式①中第一行取得了包含文档中所有<div>元素的HTMLCollection。因为这个集合是实时的,所以任何时候只要向页面中添加一个新的<div>元素,再查询这个集合就会多一项。因为浏览器不希望保存每次创建的集合,所以就会在每次访问时更新集合。每次循环都会求值i < divs.length,这意味着要获取所有<div>元素的查询。因为循环体中创建并向文档中添加一个新的<div>元素,所以每次循环divs.length的值也会递增。因为两个值都会递增,所以i永远不会等于divs.length,因此表达式①会造成死循环。
而表达式②中,又初始化了一个保存集合长度的变量len,因为len保存着循环开始集合的长度,而这个值不会随集合增大动态增长(for循环中初始化变量处只会初始化一次),所以就可以避免表达式①中出现的无穷循环问题。
如果不想初始化一个变量,也可以使用反向迭代:

表达式③:

let divs = document.getElementsByTagName("div");
for(let i = divs.length-1;i>=0;--i){
	let div = document.createElement("div");
	document.body.appendChild(div);
}

二、谈谈关于innerHTML的性能问题?

1、使用innerHTML的反面教材

for(let value of values){
	ul.innerHTML += '<li>${value}</li>';
}

这段代码效率低,因为每次迭代都要设置一次innerHTML,不仅如此,每次循环都要先读取innerHTML,也就是说一次循环要访问两次innerHTML。

2、提高代码效率

let itemsHtml = "";
for(let value of values){
	itemsHtml  += '<li>${value}</li>';
}
ul.innerHTML = itemsHtml;

这样修改之后,效率就高多了,只会对innerHTML进行一次赋值,下面代码也可以搞定:
ul.innerHTML = values.map(value => '<li>${value}</li>').join(' ');

三、如何解决类似按钮过多问题?

过多事件处理程序的解决方案是使用事件委托。事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,click事件冒泡到document。这意味着可以为整个页面指定一个onclick事件处理程序,而不是为每个可点击元素分别指定事件处理程序。

<ul id="myGirls">
	<li id="girl1">比比东</li>
	<li id="girl2">云韵</li>
	<li id="girl3">美杜莎</li>
</ul>

这里包含三个列表项,在被点击时应该执行某个操作,通常的方式是指定三个事件处理程序:

let item1 = document.getElementById("girl1");
let item2 = document.getElementById("girl2");
let item3 = document.getElementById("girl3");

item1.addEventListener("click",(event) => {
	console.log("我是比比东!");
})

item2.addEventListener("click",(event) => {
	console.log("我是云韵!");
})

item3.addEventListener("click",(event) => {
	console.log("我是美杜莎!");
})

相同代码太多,代码过于丑陋了。
使用事件委托,只要给多有元素的共同的祖先节点添加一个事件处理程序,就可以解决丑陋!

let list = document.getElementById("myGirls");
list.addEventListener("click",(event) => {
	let target = event.target;
	switch(target.id){
		case "girl1":
			console.log("我是比比东!");
			break;
		case "girl2":
			console.log("我是云韵!");
			break;
		case "girl3":
			console.log("我是美杜莎!");
			break;
	}
})

四、事件委托的优点有哪些?

  1. document对象随时可用,任何时候都可以为它添加一个事件处理程序(不用等待DOMContentLoaded或load事件),通过它处理页面中所有某种类型的事件。这意味着只要页面渲染出可点击的元素,就可以无延迟的起作用。
  2. 节省花在设置页面事件程序上的事件。
  3. 减少整个页面所需的内存,提升整体性能。
    五、你是如何解决表单的二次提交的?
    避免多出提交的代码:
let form = document.getElementById("myForm");
for.addEventListener("submit",(event) => {
	let target = event.target;
	let btn = target.elements["submit"];
	btn.disabled = true;
});

以上代码在表单的submit事件上注册了一个事件处理程序,当submit事件触发时,代码会取得提交按钮,然后将其disabled属性设置为true。注意,这个功能不能通过直接给提交按钮添加onclick事件处理程序来实现,原因是不同浏览器触发事件的时机不一样。有些浏览器会在触发表单的submit事件前先触发提交按钮的click事件,有些浏览器则会后触发click事件,对于先触发click事件的浏览器,这个按钮会在表单提交前被禁用,这就意味着表单不会被提交了。因此最好使用表单的submit事件来禁用提交按钮。

五、JavaScript思维导图

在这里插入图片描述

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值