前端基础知识(JavaScript)
文章目录
- 前端基础知识(JavaScript)
- 一、DOM和BOM
- 二、回调函数和promise用法
- 三、Ajax技术
- 四、服务器介绍
-
- [1. 什么是服务器?](#1. 什么是服务器?)
- [2. VSCode 和 IDEA 里面的服务器是什么?](#2. VSCode 和 IDEA 里面的服务器是什么?)
- [3. VSCode 和 IDEA 之间的区别:](#3. VSCode 和 IDEA 之间的区别:)
- [4.VSCode 和 IDEA 里面的服务器详细解释:](#4.VSCode 和 IDEA 里面的服务器详细解释:)
- 总结
一、DOM和BOM
DOM(文档对象模型)和BOM(浏览器对象模型)是Web开发中的两个核心概念,它们分别用于操作文档内容和控制浏览器行为。
①DOM操作主要是针对页面的属性进行修改,选取元素:使用document.getElementById("elementId"),通过元素的id来获取元素,这里获取的是元素对象,不是具体的值,如果要获取具体的值,需要在后面点出来,即:
document.getElementById("elementId").value。
②BOM操作是浏览器功能的编程接口,它提供了与浏览器窗口交互的对象,可以控制浏览器的行为。
示例1:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM,BOM操作</title>
</head>
<body>
<img src="../img/img.png" alt="图片" id="p2" style="width:300px">
<!-- 添加 onclick 属性 -->
<button onclick="button2()">点击更换图片</button>
<table id="table1"></table>
<button onclick="button1()">增加table元素</button>
<button onclick="button3()">删除数据</button>
<label for="rowsToDelete">
<input type="number" id="rowsToDelete" placeholder="请输入要删除的行数">
</label>
<button onclick="button4()">删除行</button>
<div>
<label for="username1"></label><input type="text" placeholder="输入用户名" onblur="but1()" id="username1">
<label for="password1"></label><input type="password" placeholder="输入密码,密码需大于6位数" onblur="but2()" id="password1">
<p id="p1" style="font-size:12px"></p>
</div>
<button onclick="b3()">点击弹窗</button>
</body>
<script>
//DOM操作(CRUD):
//create element
function button1() {
const tables = document.getElementById("table1");
const numberOfRowsToAdd = 7;
for (let i = 0; i < numberOfRowsToAdd; i++) {
const trs = document.createElement("tr");//create new rows
const tdsOne = document.createElement("td");//create new cell
const tdsTwo = document.createElement("td");//create new cell
tdsOne.textContent = "language:";
tdsTwo.textContent = "JavaScript";
trs.appendChild(tdsOne);//insert a new element into the parent element
trs.appendChild(tdsTwo);//insert a new element into the parent element
tables.appendChild(trs);//same as the previous line
}
}
//update element (image)
function button2() {
const imageElement = document.getElementById("p2");
console.log(imageElement);
//replace elements by imageElement.setAttribute('field', 'value')
imageElement.setAttribute("src", "../img/img1.png");
}
//delete element
function button3() {
const tables = document.getElementById("table1");
const tableChild = tables.childNodes;
if(tableChild.length>0){
for (let i = tableChild.length - 1; i >= 0; i--) {
console.log(tableChild[i]);
tables.removeChild(tableChild[i]);
}
}
}
function button4() {
const tables = document.getElementById("table1");
const tableChild = tables.childNodes;
let rowsToDelete = parseInt(document.getElementById("rowsToDelete").value);
//isNaN是一个全局函数判断是否是数字,不是数字返回true
if (isNaN(rowsToDelete) || rowsToDelete <= 0) {
alert("请输入有效的行数");
return;
}
if (tableChild.length > 0) {
for (let i = tableChild.length - 1; i >= 0 && rowsToDelete > 0; i--) {
if (tableChild[i].nodeType === Node.ELEMENT_NODE) { // 确保是元素节点
console.log(tableChild[i]);
tables.removeChild(tableChild[i]);
rowsToDelete--;
}
}
} else {
alert("没有更多的行可以删除");
}
}
//如果用户名是admin,提示用户名已存在;如果密码少于6位数,提示密码过短,需要6位数以上,以上所有提示均显示在p标签内
function but1(){
const usernames = document.getElementById("username1").value;
console.log(usernames);
if(usernames==="admin"){
document.getElementById("p1").innerHTML="用户名已存在。";}
else{
document.getElementById("p1").innerHTML="用户名可以使用。";
}
}
function but2(){
const passwords = document.getElementById("password1").value;
if(passwords.length<6){
document.getElementById("p1").innerHTML="密码过短,需要六位数以上!!";}
else{
document.getElementById("p1").innerHTML="密码可以使用。";
}
}
//BOM操作;
function b3(){
// Windows:对象
window.close();//close the page
console.log(window.document);//直接将当前页面的html页面打印出来
console.log(window.confirm("是否进入"));
window.location.href="https://www.101weiqi.com";//跳转到101网站
console.log(window.location.href);
// _blank: 在新窗口或标签页中打开链接。
// _self: 在同一框架中打开链接(默认行为)。
// _parent: 在父框架中打开链接。
// _top: 在整个窗口中打开链接。
window.open("https://www.baidu.com","_block","width:300px;height:200px");
window.open("https://www.101weiqi.com","_top","width:300px;height:200px");
window.alert("你好呀,我是37方寸");
// history:
history.go(1); //回退一页
history.go(-1); //前进一页
history.back(); //回退一页
history.forward(); //前进一页
history.length //返回历史记录的数量
history.pushState(null, null, "test.html"); //添加一个新的历史记录,并跳转到新页面
history.replaceState(null, null, "test.html"); //修改当前历史记录,并跳转到新页面
//navigator:
console.log(navigator.language)//返回浏览器的语言
console.log(navigator.userAgent)//返回浏览器的 userAgent 字符串
console.log(navigator.platform)//返回操作系统的平台
console.log(navigator.geolocation)//提供当前用户的地理位置信息
// screen:
console.log(screen.width)
console.log(screen.height)
console.log(screen.availWidth)//去除任务栏
console.log(screen.availHeight)//去除任务栏
console.log(screen.availHeight)//返回可见区域的高度
}
</script>
</html>

二、回调函数和promise用法
JS是一个单线程,它是自上而下顺序执行,如果中间有代码出现问题停止运行,那么js整个运行都会被停止。
同步: 自上而下顺序进行.
异步: 也是自上而下运行,但是当遇到问题代码时,会跳过去运行下一个
区分异步回调函数和同步回调函数。
查看内部代码的运行是否有阻塞状态,有就是同步,没有就是异步、可通过debugger在测览器后台查看
回调函数的优缺点:
优点: 简单,容易部署.
缺点: 不利于阅读与维护,各个函数之间高度耦合。
示例2:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>回调函数</title>
</head>
<body>
<p id="text"></p>
</body>
<script>
// 异步回调
// 下面就是一个简单的异步,首先调用f1函数,走到f1函数中后,第一行使用的是setTimeout,这是一个支持异步的方法,此时会暂定这一句,走到下一句.
// 下一句输出f1后,时间到达,开始返回执行第一句.
// 第一句是调用f2的函数,然后输出f2
function f2() {
console.log("f2");
}
function f1(cb) {
setTimeout(cb, 1000);
console.log("f1")
}
f1(f2);
// 为什么不直接调用原函数:
// 1:为了底层函数的安全,不被污染.
// 2:如果我们使用的是第三方的函数,我们无法直接对原函数修改,使用了回调函数,从而实现完整的功能
//
function example(value) {
//将该元素的 innerHTML 属性设置为传入的 value 值。
document.getElementById("text").innerHTML = value;
}
function callback(value) {
example(value);
}
function First() {
callback("vue3");//callback调用了example,那么example就是回调函数.
}
function Second() {
callback("37方寸");//callback调用了example,那么example就是回调函数.
}
First();
Second();
//================================================================
//买菜--> 做菜 --> 吃菜
function buy(bn) {
setTimeout(() => {
bn("买菜");
}, 2000);
}
function make(bn) {
setTimeout(() => {
bn("做菜");
}, 3000);
}
function eat(bn) {
setTimeout(() => {
bn("吃菜");
}, 1000);
}
//回调地狱.
buy(function (data) {
console.log(data);
make(function (data) {
console.log(data);
eat(function (data) {
console.log(data);
});
});
});
//promise用法:new Promise();
//主要作用,就是解决回调地狱的问题
//Promise的返回值为resolve,返回的就是异步函数里的值
//then.拿到回调函数的数据
//买菜--> 做菜 --> 吃菜
function buy(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve("买菜");
},2000);
})
}
function make(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve("做菜");
},3000);
})
}
function eat(){
return new Promise(function(resolve){
setTimeout(()=>{
resolve("吃菜");
},1000);
})
}
//串行执行
buy().then(function(data){
console.log(data);
return make();// 等待 make() 完成
}).then(function(data){
console.log(data); // 等待 eat() 完成
return eat();
}).then(function(data){
console.log(data);
});
//async函数,看着像同步,实际上异步
async function getData() {
let b = await buy();
console.log(b);
let c = await make();
console.log(c);
let d = await eat();
console.log(d);
}
getData();
</script>
</html>
问题分析:
在这个例子中,我们需要依次执行 买菜、做饭、吃饭,每个操作完成后都调用下一个操作的回调。可以看到这里的回调函数是嵌套的,每个函数里面都有一个回调,这就是典型的"回调地狱"。
- 层级嵌套:随着异步操作增多,回调函数会变得越来越多,每增加一个操作,代码层级就增加一层。
- 可读性差:代码结构混乱,不容易理解,尤其当操作链很长时,甚至可能需要滚动很长时间才能看到整个操作流程。
- 维护困难 :如果某个操作发生错误(比如
buyVegetables出错了),我们就需要在每个回调里处理错误,这样会增加额外的复杂性。
上述就是用promise改写的原因
优势:
- 链式调用: 使用
Promise,我们可以通过.then()方法将多个异步操作链接在一起,避免了回调函数的嵌套。- 每个
.then()返回的是一个新的Promise,它会接收前一个Promise的结果(如果需要),并且按照顺序执行下一个操作。
- 每个
- 提高可读性: 代码结构变得平坦,逻辑更加清晰。每个异步操作的执行顺序非常明确,
buyVegetables()完成后才会执行cookFood(),然后是eatFood(),最后打印"一天的工作完成"。 - 错误处理: 如果某个操作失败了,我们可以通过
.catch()来处理错误,而不需要在每个回调中做错误处理。
示例3:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise用法</title>
</head>
<body>
</body>
<script>
// function buyVegetables(callback) {
// setTimeout(() => {
// console.log("买菜完成");
// callback(); // 执行下一个步骤
// }, 1000);
// }
//
// function cookFood(callback) {
// setTimeout(() => {
// console.log("做饭完成");
// callback(); // 执行下一个步骤
// }, 1000);
// }
//
// function eatFood(callback) {
// setTimeout(() => {
// console.log("吃饭完成");
// callback(); // 执行下一个步骤
// }, 1000);
// }
//
// // 调用回调函数,嵌套执行操作
// buyVegetables(function() {
// cookFood(function() {
// eatFood(function() {
// console.log("一天的工作完成");
// });
// });
// });
function buyVegetables() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("买菜完成");
resolve(); // 操作完成,进入下一个步骤
}, 1000);
});
}
function cookFood() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("做饭完成");
resolve(); // 操作完成,进入下一个步骤
}, 1000);
});
}
function eatFood() {
return new Promise((resolve) => {
setTimeout(() => {
console.log("吃饭完成");
resolve(); // 操作完成,进入下一个步骤
}, 1000);
});
}
// 使用 Promise 链式调用
buyVegetables()
.then(() => cookFood())
.then(() => eatFood())
.then(() => {
console.log("一天的工作完成");
})
.catch((error) => {
console.error("发生错误:", error);
});
async function doDailyWork() {
await buyVegetables();
await cookFood();
await eatFood();
console.log("一天的工作完成");
}
doDailyWork();
</script>
</html>
三、Ajax技术
ajax----> async javascript and xml(闭合标签),就是异步的javascript和xml的技术。以前从后端拿取数据,或者向后端发送数据,就是用xml格式(标签格式)去发送;现在,主要还是用json格式,只需要通过JSON.parse()就可以解析json数据。
示例4:发送ajax请求
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax</title>
</head>
<body>
<script>
//1:创建一个ajax请求
var xhr = new XMLHttpRequest();
console.log(xhr);
//2.配置open(配置请求方式,请求地址,是否异步)
// xhr.open("get","http://localhost:63342/javascript_project/js_1/1.json",true);
xhr.open("get","http://127.0.0.1:5500/test.json",true);//true表示异步
//3.send request
xhr.send();
// readyState ===0:表示请求未完成初始化,也就是open方法还没执行(`UNSENT`)
// readyState ===1:表示配置信息已经完成,也就是执行完open以后(`OPENED`)(服务器已经建立连接)
// readyState ===2:表示send方法已经执行完成.(`HEADERS_RECEIVED`)(请求已接受)
// readyState ===3:表示正在解析响应内容.(`LOADING`)(请求处理中)
// readyState ===4:表示响应内容已经解析完毕,可以在客户端里使用(`DONE`)(请求已完成)
//4接受数据,注册时间,这个方法会回调四次,一共有四次变化
xhr.onreadystatechange = function(){
console.log("readyState:", xhr.readyState); // 打印请求的当前状态
if (xhr.readyState === 4) { // 请求已完成
if (xhr.status === 200) { // 请求成功
console.log("Response Text:", xhr.responseText); // 打印返回的内容
document.write(xhr.responseText); //显示到当前页面
} else {
console.log("Error: " + xhr.status); // 打印错误状态码
// document.write("找不到数据");
location.href="404.html";
}
}
}
//使用txt文本内容
xhr.onload = function(){
console.log(xhr.readyState);
if(xhr.status===200){
document.write(xhr.responseText);
}else if(xhr.status===404){
document.write("document could not be found");
}
}
//使用json格式
xhr.onload = function(){
console.log(xhr.readyState);
if(xhr.status===200){
//控制台输出文本内容
console.log(xhr.responseText);
//页面这里输出object
document.write(JSON.parse(xhr.responseText).home);
}else if(xhr.status===404){
document.write("document could not be found");
}
}
//==============================================
</script>
</body>
</html>
整个过程可以总结为:
- 创建 XMLHttpRequest 对象,用于发起请求。
- 配置请求 ,指定请求方法(
GET)和请求的 URL(https://www.baidu.com)。 - 发送请求 ,通过
xhr.send()向服务器发送请求。 - 处理响应 ,通过监听
onreadystatechange事件来判断请求状态,当请求完成并且成功时(readyState == 4且status == 200),可以处理返回的数据。
四、服务器介绍
1. 什么是服务器?
服务器(Server)是指一种计算机系统、硬件设备或者程序,它提供网络服务、资源、数据、功能或应用程序给客户端(Client)。简单来说,服务器是一种提供服务的计算机,它通常在网络上等待并响应客户端的请求。
- 硬件层面:服务器通常是性能较高的计算机,配置上比普通桌面计算机更强,专门用于提供某种服务(如 Web 服务、文件服务、数据库服务等)。
- 软件层面:服务器也可以指提供服务的软件程序,例如 Web 服务器(Apache、Nginx)、数据库服务器(MySQL、PostgreSQL)等。
2. VSCode 和 IDEA 里面的服务器是什么?
VSCode 中的服务器:
VSCode 本身是一个轻量级的文本编辑器,并没有内置 Web 服务器功能。但它可以通过插件来扩展功能,比如 Live Server 插件。这个插件通过启动一个本地 HTTP 服务器,允许你查看和测试 HTML、CSS 和 JavaScript 文件。
- Live Server :它是一个简单的本地开发服务器,通常监听一个端口(比如
http://127.0.0.1:5500/),当你编辑和保存文件时,页面会自动刷新。这个服务器只是用于开发时的快速预览,并不适合生产环境。
VSCode 本身没有自带 Web 服务器,因此开发者需要通过插件或外部工具来启动本地服务器。
IntelliJ IDEA 中的服务器:
IntelliJ IDEA 是一个集成开发环境(IDE),它不仅支持编辑代码,还支持运行和调试应用程序。IDEA 本身包含内置的 Web 服务器,尤其在开发 Java Web 应用时(如 Spring、Servlet 等),你可以直接运行和调试应用,而不需要单独启动一个 Web 服务器。
- 内置服务器 :IDEA 提供了类似 Jetty 或 Tomcat 等 Web 服务器的支持,允许开发者直接在 IDE 中运行 Web 应用程序。它会启动一个本地的 HTTP 服务器(通常在
localhost和一个端口上),从而可以直接在浏览器中访问应用程序。
3. VSCode 和 IDEA 之间的区别:
| 特性 | VSCode | IntelliJ IDEA |
|---|---|---|
| 类型 | 轻量级的文本编辑器,支持插件扩展 | 完整的集成开发环境(IDE),功能非常强大 |
| 默认服务器 | 没有内置服务器,需要通过插件(如 Live Server)来启动 | 提供内置的服务器(如 Tomcat, Jetty)用于运行 Java Web 应用 |
| 使用场景 | 适合简单的静态网站、前端开发,且快速预览 | 适合大型项目,尤其是 Java Web 开发,支持调试和部署 |
| 配置复杂度 | 插件需要手动配置,但相对简单 | 配置较复杂,尤其是 Java 项目,支持复杂的应用程序配置 |
| 支持的语言 | 支持多种语言,主要是前端开发,如 JavaScript, HTML, CSS | 支持多种语言,尤其是 Java,适合后端开发 |
| 常用的开发模式 | 本地开发和快速预览,适合前端开发和小型项目 | 本地开发、调试和部署,适合 Java 和企业级项目 |
4.VSCode 和 IDEA 里面的服务器详细解释:
VSCode 中的服务器:
- 插件支持 :VSCode 本身并不自带 Web 服务器功能,你需要安装 Live Server 插件来启动本地开发服务器。
- 开发场景 :VSCode 非常适合前端开发,尤其是 HTML、CSS 和 JavaScript 文件。在开发过程中,
Live Server会帮助你快速预览文件的变化,并自动刷新浏览器。
IDEA 中的服务器:
- 内置支持:IntelliJ IDEA 提供了内置的 Web 服务器(如 Jetty 或 Tomcat),这意味着你可以直接在 IDEA 中启动一个 Web 服务器来运行和调试 Web 应用。尤其对于 Java Web 应用,IDEA 的内置支持使得你不需要手动配置外部 Web 服务器。
- 开发场景:IDEA 主要用于开发大型应用,尤其是 Java 后端应用程序,支持复杂的项目结构、自动化构建、调试和部署等功能。
总结
BOM(浏览器对象模型)提供了与浏览器窗口交互的接口,用于控制浏览器的导航、历史记录和屏幕信息等;DOM(文档对象模型)则将HTML文档表示为树形结构,允许JavaScript动态操作网页内容、样式和结构。回调函数是一种作为参数传递给其他函数的函数,在异步操作完成后被调用以处理结果。AJAX技术则通过XMLHttpRequest或Fetch API实现浏览器与服务器的异步数据交换,无需刷新页面即可更新网页内容,从而提升用户体验。