前端基础知识(JavaScript)

前端基础知识(JavaScript)

文章目录


一、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改写的原因
优势:

  1. 链式调用: 使用 Promise,我们可以通过 .then() 方法将多个异步操作链接在一起,避免了回调函数的嵌套。
    • 每个 .then() 返回的是一个新的 Promise,它会接收前一个 Promise 的结果(如果需要),并且按照顺序执行下一个操作。
  2. 提高可读性: 代码结构变得平坦,逻辑更加清晰。每个异步操作的执行顺序非常明确,buyVegetables() 完成后才会执行 cookFood(),然后是 eatFood(),最后打印 "一天的工作完成"
  3. 错误处理: 如果某个操作失败了,我们可以通过 .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>

整个过程可以总结为:

  1. 创建 XMLHttpRequest 对象,用于发起请求。
  2. 配置请求 ,指定请求方法(GET)和请求的 URL(https://www.baidu.com)。
  3. 发送请求 ,通过 xhr.send() 向服务器发送请求。
  4. 处理响应 ,通过监听 onreadystatechange 事件来判断请求状态,当请求完成并且成功时(readyState == 4status == 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 提供了类似 JettyTomcat 等 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实现浏览器与服务器的异步数据交换,无需刷新页面即可更新网页内容,从而提升用户体验。

相关推荐
Whisper_Sy2 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 应用列表实现
android·开发语言·javascript·flutter·php
小CC吃豆子2 小时前
Python爬虫
开发语言·python
机器视觉知识推荐、就业指导2 小时前
Qt 6 所有 QML 类型(官方完整清单 · 原始索引版)
开发语言·qt
json{shen:"jing"}3 小时前
1. 两数之和
前端·javascript·数据库
techdashen3 小时前
Rust OnceCell 深度解析:延迟初始化的优雅解决方案
开发语言·oracle·rust
github.com/starRTC3 小时前
Claude Code中英文系列教程19:使用subagent子代理与创建自定义子代理【重要】
前端·javascript·数据库
少控科技3 小时前
QT新手日记033
开发语言·qt
hua_ban_yu3 小时前
vue3 + ts 制作指令,防止按钮在固定时间内重复点击,不会影响到表单的校验
前端·javascript·vue.js
老神在在0013 小时前
Token身份验证完整流程
java·前端·后端·学习·java-ee