js中级

111 阅读6分钟

一. 变量的声明

(一) 变量var

  • 可以重复声明, 后面的声明会覆盖前面的
  • 没有块作用域 (ES5 只有函数作用域, 没有块作用域)

(二)变量let

  • Es6新增了let命令,不能重复声明, 有块级作用域

(三)常量const

  • 必须要给初始值
  • 定义常量, 不能重复声明
  • 如果const 定义的是数组和对象,那么修改其中的内容,是可以的

二. 嵌套循环

  • 循环中再写循环就叫循环嵌套
let arr = [
            {name: "小貂蝉", hobs: ["html", "css", "js"]},
            {name: "阳仔", hobs: ["捏脚", "spa", "LOL"]},
            {name: "张三", hobs: ["捏脚", "瑜伽", "LOL"]}
        ]
        // 目的:取出每一个人的爱好,并打印在控制台上
        // 1.先取第一层的元素
        for (let i = 0; i < arr.length; i++) {
            // 2.第一层的元素是对象,取hobs,arr[i].hobs
            // console.log(arr[i]);

            // 3.hobs是一个数组,再用for循环去hobs中的每一个元素
            // console.log(arr[i].hobs)
            for(let j = 0; j < arr[i].hobs.length; j++) {

                // 4.取出每一个人的爱好,并打印在控制台上
                console.log( arr[i].name, arr[i].hobs[j]);
            }
        }

三. 函数专题

(一)函数的写法

  • 声明式
//ES5 
function getSum(){} 
function (){}//匿名函数 
//ES6
()=>{}
//如果{}内容只有一行 那{}和return关键字可省,
  • 表达式
//ES5
var sum=function(){} 
//ES6
let sum=()=>{}//如果{}内容只有一行{}和return关键字可省,
  • 构造函数
const sum = new Function('a', 'b' , 'return a + b')

(二)函数的作用

  • 复用封函数,变化设参数
  • 如果需要实现一个功能,而且这个功能的代码函数超过5行,功能到处用,就可以封装函数了
 // 写一个函数,计算身高体重的健康指数(BMI):
 // 计算公式为:BMI=体重(千克)除以身高(米)的平方。

// 声明这个参数
function calcBMI(weight, height) {
     // 函数体的逻辑
     return weight / (height * height) ;
}      

// 直接去使用函数
console.log(calcBMI(45, 1.6))

(三)函数的参数

  • 形参:定义函数时的参数,取啥名都可以,最好还是语义化
  • 实参:调用函数时,实际传入的参数 ,实参和形参是一一对应的
  • 默认参数:
// ES5 写法: 默认参数的写法
function fn(num) {
    let temp = num || 0;   
}
// ES6默认参数的写法
function fn(num = 0) {}
  • arguments: 伪数组:具有length属性;可以使用for循环。
// 实现一个不定参数的求和的函数;
 function sum() {
        // 1.获取所有的参数
        console.log(arguments)
        let res = 0;
     
        // 2.直接对arguments里面的所有元素进行求和
        for(let i = 0; i < arguments.length; i++) {
              res += arguments[i];
        }
        return res;
 }
  
  // 3.函数的使用
  let resSum = sum(1, 2 ,3 ,4);
  console.log(resSum);

(四)函数的返回值

  • 哪里调用该函数,返回值就返回到哪里(调哪返哪)
  • 没有return,函数的返回值是undefined

四. 数组的API

  • 不影响原数组的api

1.concat 连接数组

let arr1 = ["hello"];
let arr2 = ["秀儿"];
let res = arr1.concat(arr2);

2.join :可以将数组转化为字符串

let res = arr1.join(分隔符)

3.indexOf:如果参数不是数组的中的元素,返回值-1;若是,从数组的第0项开始匹配,匹配到了,则返回下标值

let index = arr1.indexOf(某一项元素)

4.lastIndexOf: 和indexOf匹配的方向相反,匹配到了,则返回下标值。如果参数不是数组的中的元素,返回值-1

let index = arr1.lastIndexOf(某一项元素)

5.slice: 从已有的数组中返回选定的元素

let resArr = array.slice(start, end)

6.includes: 用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false

let flag = arr.includes(某一项元素)

7.flat: 嵌套数组转一维数组

let newArray = arr.flat(depth)
  • 影响原数组的api 1.reverse: 反转数组
let newArr = arr1.reverse();

2.splice:方法用于添加或删除数组中的元素

let newArray = arr1.splice(index,howmany,item1,.....,itemX)

// 删除元素
let arr = ["html", "css", "js"];
let resArr = arr.splice(1, 1)
console.log("原数组:", arr);
console.log("返回值:", resArr);

// 可以从任意位置对数组进行删除和增加
let resArr = arr.splice(1, 1, 2, 3);
console.log("原数组:", arr);
console.log("返回值:", resArr);

3.push: 向数组末尾添加一个或多个元素

let res = arr.push(元素)
# 也可添加多个元素
let res = arr.push(元素1, 元素2, ...)

4.pop: 把数组末尾元素删除

let res = arr.pop()

5.shift:删除并返回数组的第一个元素

let res = arr.shift();

6.unshift: 向数组的开头添加一个或多个元素,并返回新的长度

let resL = arr.unshift(元素)
# 也可添加多个元素
let res = arr.unshift(元素1, 元素2, ...)
  • sort: 方法用于对数组的元素进行排序
let res = array.sort(function(a, b) {
    // return a - b // 升序
    // return b - a // 降序
})

五. 遍历数组

1.forEach:遍历数组

arr.forEach(function(val, index) {
    // 处理逻辑
})

2.map:使用返回值的,遍历数组的一个方法

// map会创建一个新的空数组,将原数组遍历之后,对每个元素进行操作,返回到新数组中
let newArray = arr.map(function(val, index) {
    // 处理逻辑
    return xxx
})

3.filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素

let newArray = arr.filter(function(val, index) {
    return 过滤条件
})

4.every() 方法用于检测数组所有元素是否都符合指定条件,符合是true,否则false

let res = arr.every(function(val, index) {
    return 符合条件
})

5.some() 方法用于检测数组中的元素是否满足指定条件

let res = arr.some(function(val, index) {
	return 符合条件
})

6.find() 方法返回通过测试(函数内判断)的数组的第一个元素的值

let res = arr.find(function(val, index) {
	return 符合条件
})

7.findIndex() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置

let res = arr.findIndex(function(val, index) {
	return 符合条件
})

六. Object的两个方法

1.Object.assign()---合并

# 要用于将一个或多个源对象复制到目标对象,它将返回目标对象。
# 参数中的目标对象通常用{}
let targetObj = Object.assign(目标对象,源对象1,源对象2, 源对象3, ...)

注意:合并时,如果存在相同的key,则后面的会覆盖前面的

1.Object.keys()---合并

# Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组。
let keysArr = Object.keys(obj);

// 常见用法: 使用Object.keys()遍历对象
Object.keys(obj2).forEach(function(val, index) {
        console.log(val, obj2[val])
})

七. Date对象

// 目的:给日期补0
function getCurrentTime() {
    let date = new Date();
    // 1.先获取年月日
    // 用来获取年限
    let Y = date.getFullYear();

    // 从 Date 对象返回月份 (0 ~ 11)
    let M = date.getMonth() + 1;

    // 用来获取日期的
    let D = date.getDate();

    // return [Y, M, D].map(function(val) {
    //     return val > 10 ? val : "0" + val;
    // }).join("/");

    // newArr [2022, "07", "05"]
    let newArr = [Y, M, D].map(function(val) {
        return val > 10 ? val : "0" + val;
    });

    // newStr "2022/07/05"
    let newStr = newArr.join("/")

    return newStr;
}
console.log(getCurrentTime());

八. 正则表达式

1. 正则表达式js提供的一套规则,用来处理字符串的,具有强大的字符串处理能力

2. 正则表达式的写法

const reg = new RegExp("表达式""修饰符") // 修饰符是可选的
示例:
new RegExp("abc", "i"); // i代表不区分大小写

const reg = /表达式/修饰符;

// 检测字符串是否符合正则表达式的规则,若符合,则返回true,否则返回false
正则.test(字符串) 

3. 正则表达式的示例

// 验证手机号
# 1.要以1开头。 2.位数11位。 3. 13 14... 19开头的手机号
# [12345] [1-5]:只匹配一个  [1-5]{10} {2, 10} 
const reg = /^1[3-9][0-9]{9}$/;
reg.test("13522223333");

// 验证邮箱
# 邮箱:xxx@qq.com xxx@163.com  xxx@itsource.cn com|cn|org|cc
const reg = /^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.(com|cn|org|cc)$/
reg.test("邮箱号")

九. 注册表单验证

 // 1.获取dom
        let userNameIpt = document.querySelector("#userNameIpt");
        let emailIpt = document.querySelector("#emailIpt");
        let passwordIpt = document.querySelector("#passwordIpt")
        let regBtn = document.querySelector(".reg-btn");

        let tips = document.querySelectorAll(".tips");

        // 增加标识
        let usernameFlag = false;
        let emailFlag = false;
        let passwordFlag = false;
	
        function checkUsername() {
            // 获取用户输入的用户名
            let username = userNameIpt.value;

            // 用户名的正则表达式 中文、字母、数字、下划线 长度2~12位
            const userNameReg = /^[\u4E00-\u9FA5a-zA-Z0-9_]{2,12}$/;

            if (userNameReg.test(username)) {
                // console.log("你输对了")
                tips[0].style.color = "#ccc";
                usernameFlag = true;
            } else {
                // 输错之后的提示:提示变红
                tips[0].style.color = "red"
                usernameFlag = false;
            }
        }

        // 失焦事件监听
        userNameIpt.addEventListener("blur", checkUsername);


        function checkEmail() {
            let email = emailIpt.value;

            // 邮箱的正则表达式:有效的邮箱
            const emailReg = /^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+$/;


            if (emailReg.test(email)) {
                tips[1].style.color = "#ccc";
                emailFlag = true;
            } else {
                tips[1].style.color = "red";
                emailFlag = false;
            }
        }

        emailIpt.addEventListener("blur", checkEmail)


        function checkPassword() {
            let password = passwordIpt.value;

            // 密码的正则表达式:字母、数字、下划线长度6~12位
            const passwordReg = /^[a-zA-Z0-9_]{6,12}$/;

            if (passwordReg.test(password)) {
                tips[2].style.color = "#ccc";
                passwordFlag = true;
            } else {
                tips[2].style.color = "red"
                passwordFlag = false;

            }
        }

        passwordIpt.addEventListener("blur", checkPassword)

        regBtn.addEventListener("click", function () {
            if (usernameFlag && emailFlag && passwordFlag) {
                console.log("全部验证通过,可以注册了")
            } else {
                console.log("验证不通过,请检查")
            }
        })

十. 事件对象

1.事件对象: 触发事件时,事件对象会作为默认参数默认传入到function中

2.事件对象的属性

  • e.target: 事件源
  • e.type: 事件类型
  • e.clientX: 水平坐标
  • e.clientY: 垂直坐标
  • e.keyCode: 键盘码
  • e.which: 鼠标按键的值

3.事件对象的方法

  • e.preventDefault() ---阻止浏览器的默认行为 / 阻止a标签的跳转
  • e.stopPropagation() ---阻止事件冒泡

4.事件委派

  • 事件委派,就是嵌套内部的标签需要触发的事件,不直接绑到嵌套内部的标签,而是把事件绑定到父标签上
  • 事件委派的好处:提高性能; 动态渲染的标签也可以触发事件
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <ul id="list">
      <li>111</li>
      <li>222</li>
      <!-- ---- -->
    </ul>

    <script>
      setTimeout(function () {
        // 创建一个li标签
        let li = document.createElement("li");
        // 添加内容
        li.textContent = "我是新来的";
        // 加入ul中
        list.appendChild(li);
        // console.log("9999");
      }, 3000);

      // 获取ul
      const list = document.querySelector("#list");

      // 获取所有li
      // const lis = document.querySelectorAll("li");
      // // 循环绑定事件
      // lis.forEach(function (li) {
      //   li.addEventListener("click", function () {
      //     console.log("666");
      //   });
      // });

      // 事件委托(事件委派 / 事件代理):  本来是给儿子绑定的事件 委托给了父亲绑定
        list.addEventListener("click", function () {
          console.log("5555");
        });
    </script>
  </body>
</html>

十一. Ajax

1.介绍

  • Ajax是一种前端和服务端交互的技术,从服务端获取的数据可以动态的渲染到页面上。页面是局部刷新的

2.原生Ajax发送get请求

// 1.创建Ajax对象
let xhr = new XMLHttpRequest();

// 2.配置请求方法和请求地址 (后端给的 参数的确定也是后端的)
xhr.open("get", "url?参数名1=参数值1&参数名2=参数值2");

// 3.发送请求
xhr.send();

// 4.监听Ajax对象的状态,在合适的时候,接收数据
xhr.onreadystatechange = function () {
// readyState Ajax对象的状态码   status  http请求的状态码
    if (xhr.readyState === 4 && xhr.status === 200) {
        let data = JSON.parse(xhr.responseText); // 字符串转为对象
        console.log(data);
    }
};

3.原生Ajax发送post请求

// 1.创建Ajax对象
let xhr = new XMLHttpRequest();

// 2.配置请求方法和请求地址 (后端给的)
xhr.open("post", "url");

// 3. 设置请求头 ( 设置参数的格式 )   
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 4. 发送Ajax请求
xhr.send('参数名1=参数值1&参数名2=参数值2')
---------------------------------------------
// 3. 设置请求头 ( 设置参数的格式 )
xhr.setRequestHeader('Content-Type', 'application/json')
// 4. 发送Ajax请求
xhr.send(JSON.stringify({name: '参数值'}))
    
    
// 5.监听Ajax对象的状态,在合适的时候,接收数据
xhr.onreadystatechange = function () {
    // readyState Ajax对象的状态码   status  http请求的状态码
    if ( xhr.readyState === 4 && xhr.status === 200) {
        let data = JSON.parse(xhr.responseText); // 字符串转为对象
        console.log(data)
    }
};

4.Ajax对象的状态码

-   0 请求未初始化
-   1 服务器连接已建立,但是请求还没接收
-   2 请求已接收
-   3 请求处理中,如果数据量过大,数据没有全部发送。
-   4 **请求已完成,且响应已就绪**

5.http请求的状态码

-   200 请求已成功
-   301 永久重定向
-   302 临时重定向
-   304 缓存
-   400 请求参数有误
-   403 服务器拒绝你的请求
-   404 请求方式有误或者请求地址不对
-   5xx 服务端(后端)发生错误

6.## Ajax调试

-   1.看地址(后端给的地址)
-   2.看请求方式和请求状态 (请求方式对不对-要看文档,请求状态----绿色表示成功)
-   3.看参数
-   4.看响应值

十二. axios

1.介绍

  • axios是基于原生Ajax封装的一个用于前后端交互的库

2.引入axios

// 1.在线获取
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.0.0-alpha.1/axios.js"></script>

// 1.bootcdn搜索 https://www.bootcdn.cn/
// 2.  https://cdn.bootcdn.net/ajax/libs/axios/1.0.0-alpha.1/axios.js
// 3.创建本地文件复制该文件。
// 4.本地引入
<script src="./lib/axios.js"></script>

3.发送get请求

axios.get(url?参数名1=参数值1&参数名2=参数值2).then(function(res) {
    // response 请求接口之后的响应值 需要的数据 res.data
    console.log(res.data)
})


axios.get(url, {
    params: {
        参数名1: 参数值1,
        参数名2: 参数值2,
        参数名3: 参数值3,
        ...
    }
}).then(function(res) {
    // response 请求接口之后的响应值 需要的数据 res.data
    console.log(res.data)
})

4.发送post请求

axios.post(url, {
        参数名1: 参数值1,
        参数名2: 参数值2,
        参数名3: 参数值3,
        ...
}).then(function(res) {
    // response 请求接口之后的响应值 需要的数据 res.data
    console.log(res.data)
})