JS高级 第一天

211 阅读2分钟

JS高级

箭头函数

与JS基础 函数一致,用法更加简洁高级

<script>
        // JS基础中 函数写法
        function func1(num1) {
            return num1 + 100
        }

        // JS高级中 使用箭头函数
        const func2 = (num1) => num1 + 100

        // 没有形参 没有返回值 2行代码
        const func3 = () => {
            console.log(`执行1`);
            console.log(`执行2`);
        } 

        // 没有形参 没有返回值 1行代码 大括号都可以省略
        const func4 = () => console.log(`执行1`);

        // 一个形参 没有返回值 1行代码
        // const func5 = (num1) => console.log(num + 1);
        const func5 = num1 => console.log(num + 1);
        
        // 两个以上形参(括号不能省略) 没有返回值 1行代码
        const func6 = (num1,num2) => console.log(num1+num2);

        // 没有形参 有返回值 2行代码
        const func7 = () => {
            let num = 100
            return num + 100
        }

        // 没有形参 有返回值 1行代码
        const func8 = () => {
            return 100 + 200
        }

        // 没有形参 有返回值 1行代码 等价上述写法
        const func9 = () => 100 + 200

        let btn = document.querySelector(`button`)
        btn.addEventListener(`click`,()=>{
            console.log(123);
        })
</script>

数组常见方法

一、forEach

1.数组每个元素都执行一次回调函数 与JS基础中for循环类型

2.for循环可以通过break打断 forEach不可以通过break打断

3.forEach 是高阶函数

<script>
        const arr = [`a`,`b`,`c`]
        
        // for循环 可以break打断 forEach不能通过break打断
        arr.forEach((value,index)=>{
            console.log(`值 是${value} 下标 是${index}`);
        })

        // 相同 写法 
        arr.forEach((value,index)=>console.log(`值 是${value} 下标 是${index}`))
    
        // 一个形参时
        arr.forEach(value=>console.log(`值 是${value}`))
</script>

二、map

根据原来的数组返回新的数组(循环数组,在循环的回调函数中返回数据,组装成新的数组)

<script>
	const arr1 = [`a`,`b`,`c`] //组装新数组 添加`我的字母是`
    const newArr1 = arr1.map((value)=>`我的字母是`+value)
    console.log(newArr1);

    const arr2 = [10,11,12] //组装新数组 [11,12,13]
    const newArr2 = arr2.map(value=>value+1)
    console.log(newArr2);

    const arr3 = [{name:`悟空`},{name:`八戒`}] //组装新数组 添加color:`red`
    const newArr3 = arr3.map((value)=>{
          value.color = `red`
          return value
    })
    console.log(newArr3);

    const arr = [`刘德华`,`郭德纲`,`林志颖`] //组装新数组 添加DIV标签渲染页面
    const newArr = arr.map((value)=>`<div>${value}</div>`)
   	const html = newArr.join(``)
    document.body.innerHTML=html

    // 究极写法
    let renderHTML = value=>`<div>${value}</div>`
    document.body.innerHTML=[`刘德华`,`郭德纲`,`林志颖`].map(renderHTML).join(``)
</script>

捐赠管理系统-map渲染

<script>
	function render() {
         // 只能使用 map方法 和 数组转方式方法 join 来实现 拼接html的功能
         // 把 arr  转成(map、join 来实现功能) 变量 html 让下面的代码 (tbody.innerHTML = html;) 执行成功
 
         let newArr = arr.map((value) =>{
              return `<tr>
                <td>${value.id}</td>
                <td>${value.person}</td>
                <td>${value.unit}</td>
                <td>${value.money}</td>
                <td>${value.date}</td>
                <td>
          <a href="#" class="del"></a>
          <a href="#" class="update"></a>
                  </td>
            </tr>`
          })
         let html = newArr.join(``)
         tbody.innerHTML = html;
    }
 
       // 根据数组数组渲染页面
       render();
</script>

运用map返回数组对象

<script>
        let arr = [`a`,`b`,`c`] //返回三个对象 name:`a`...
        let newArr = arr.map((value)=>{
            return {name:value}
        }) // 写法1
        
        let newArr2 = arr.map((value)=>({name:value}))
        console.log(newArr2); // 写法2


        console.log(newArr);
        const func = (num) => {a:123} //返回undefined JS不知道你是块级空间还是对象
        const func1 = (num1) => {
            return {a:123}
        } //返回对象 这个时候就明确了

        const func2 = (num2) => ({a:123}) //返回对象 加小括号表示 返回里面数据 也就是return {a:1}
        console.log(func2);

</script>

大括号表示两种含义:对象 或 块级空间

1650517707100

区别点

1650517769017

总结

1650517780306

三、every

判断如果数组中每一个元素是否符合条件 返回true和false

<script>
	let arr = [1,3,4] // 判断数组每个元素是否都大于5

	let result = arr.every((value) => {
		if(value>5){
			return true
  		}else{
			return false
		}
	})
    console.log(result);

    let arr2 = [true,false,true,true] //只要有一个false 返回false
    let result2 = arr2.every((value) => {
        if(value===true){
            return true
        }else{
            return false
        }
    })
    console.log(result2);

    // 如果是空数组 调用every 直接返回true
    let arr1 = []
    let result1 = arr1.every((value)=>console.log(`我是真的`))
    console.log(result1);
</script>

使用场景:全选框和复选框案例

<script>
// 给每一个商品绑定点击事件
    for (let index = 0; index < checkboxList.length; index++) {
      checkboxList[index].addEventListener('click', function () {
        
        // 判断是否达到了全选 条件
        // 判断每一个小小的复选框的选中状态 如果都是true,那么就全选

        // let checked = checkboxList.every((value)=>{
        //     if(value.checked===true){
        //         return true
        //     }else {
        //         return false
        //     }
        // })
     let checked = checkboxList.every((value)=>value.checked)
       // 设置全选按钮即可
        checkAll.checked = checked;
      });
</script>

细节:因为获取的是伪数组,需要转换为数组 才可以使用every方法

<script>
	let checkboxList = document.querySelectorAll('.ck');
    // checkboxList 现在是一个伪数组
    checkboxList=[...checkboxList];// OK  不能用concat 提取还是伪数组

     let li = document.querySelectorAll(`li`) //伪数组
      // 之前使用转数组方式太LOW

      // 第一种
      let liArr = [].concat(li) 
      console.log(liArr); // 弊端 嵌套了
      // liArr = [li伪数组] => liArr[0] = li伪数组 还是不能使用every方法

       // 第二种
       let liArr2 = [...li]
       console.log(liArr2);
</script>

踩坑点:

1650518144064

1650518202993

四、some

检测数组中只要有一个符合条件就返回true(与every类似)

五、filter

过滤满足条件的数据,组装新数组

<script>
    let arr = [1,2,3,4,5,6,7] // 返回奇数

    let newArr = arr.filter((value)=>{
        if(value%2!==0){
            	return true
        	}else{
            	return false
        	}
        })
            console.log(newArr);
</script>

使用场景:代办列表计算需求

<script>
 unfinish.innerText=`${arr.filter((value)=>!value.checked).length}项未完成`
    
 finish.innerText=arr.filter((value)=>value.checked).length
</script>

面向对象

一、面向对象思维

是一种行业通用 写项目级代码的思维,引导我们编写高质量代码

万物皆对象,特点是封装和继承

对象在内存中示意图

1650529072591

细节:对象在栈中创建的是一个地址,然后指向堆中的数据

二、创建对象方法

1.字面量

<script>
        let obj1 = {username:`悟空`,height:`180`}
        let name1 = 123
        let obj2 = {username:`悟空`,height:`180`}
        let name2 = 123
        let obj3 = {username:`悟空`,height:`180`}
        let name3 = 123
        let obj4 = {username:`悟空`,height:`180`}
        let name4 = 123

        // 字面量对象 也就是字面看到的 这样使用不方便维护和维修
        // 例如 当数据量大 想要修改name属性 为username =>使用工厂函数
</script>

2.工厂函数

缺点:失去血缘关系,无法简单分辨对象的特征。后期无法实现继承

<script>
        // 方便维护 这个时候想要更换name为username,直接改
        function createPerson(name,age,height) {
            return {
                // name : name,
                username:name,
                age:age,
                height:height
            }
        }

        let obj1 = createPerson(`黄某`,22,180)
        let obj2 = createPerson(`黄某2`,22,180)
        let obj3 = createPerson(`黄某3`,22,180)
        console.log(obj1);
        console.log(obj2);
        console.log(obj3);

        // 弊端:无法实现 继承的作用 例如儿子无法继承父亲的
</script>

3.构造函数

<script>
        // 声明一个函数 首字母大写 行内规范
        function CreatePerson(name,age,height) {
            //固定写法 给this赋值
            this.name=name,
            this.age=age,
            this.height=height
            this.color = `red` // 固定就写死,不用给变量了
        }

        // 通过 new的方式 创建对象
        const obj1 = new CreatePerson(`悟空`,100,180)
        const obj2 = new CreatePerson(`八戒`,100,160)
        console.log(obj1);
        console.log(obj2);
</script>

构造函数的弊端,同一个say方法占据两份内存

<script>
        function CreatePerson(name) {
            this.name=name,
            this.say=function(){
                console.log(`我是一个say方法`);
            }
        }

        const obj1 = new CreatePerson(`悟空`)
        const obj2 = new CreatePerson(`八戒`)

        //当我判断两个obj的say方法, 返回false 原因:两个say是不相同的内存空间
        console.log(obj1.say===obj2.say);
</script>

1650529421590

解决方法:提取用一个say方法

<script>
        function say(){
            console.log(`我是公用的方法`);
        }

        function CreatePerson(name) {
            this.name = name,
            this.say = say
        }

        const obj1 = new CreatePerson(`悟空`)
        const obj2 = new CreatePerson(`八戒`)

        console.log(obj1.say===obj2.say);
</script>

1650529847984

构造函数性能问题总结

1.基本类型和引用类型"="的不同

1650529935652

1650529974215

2.缺点:会导致全局变量的污染,很容易导致覆盖 不够优雅

1650530003237

3.优点:方便代码维护,也解决了性能的问题

原型(对象)模式(解决全局污染问题)

​ 1.原型对象是JS自动帮我们添加的,是很合构造对象存在的一个对象

​ 2.把构造函数看成人 原型对象就是人的DNA,修改DNA 构造函数的实例也会发生改变

​ 3.原型上一般式挂载函数

1650530933131

<script>
        function CreatePerson(name) {
            this.name=name
        }

        // 解决了 全局污染的问题 也解决了性能的问题 最常用方式
        CreatePerson.prototype.say = function(){
            console.log(`你好`);
        }

        const obj1 = new CreatePerson(`悟空`)
        const obj2 = new CreatePerson(`八戒`)
        
        function CreatStudents() {}

        // 无全局污染问题
        CDATASection.prototype.say = function(){
            console.log(`学生们好`);
        }

</script>

总结:构造函数内只放属性,原型对象里都是放方法 (记忆)

三、面向对象-初体验

补充知识

<script>
        // 创建不同人 都有自己名字 共同一个行为 say 打印自己名字
        function Cperson(name) {
            this.name = name
        }

        Cperson.prototype.say = function(){
            // this 指向了实例 通过this 实现了 数据传递 = 访问了构造函数的数据
            console.log(this.name);
        }

        let obj1 = new Cperson(`八戒`)
        let obj2 = new Cperson(`悟空`)
        obj1.say()
        obj2.say()
        
</script>

案例

<script>
        // 需求: 通过new Myimg(`图片地址`),页面会出现一张图片 然后点击按钮 放大缩小

        function Myimg(src) {
            let img = document.createElement(`img`)
            img.src = src
            document.body.appendChild(img)

            this.dom=img
        }

        Myimg.prototype.scale = function () {
            this.dom.classList.add(`scale`)
        }

        let img1 = new Myimg(`./9.5/01.jpg`)

        let btn = document.querySelector(`button`)

        btn.addEventListener(`click`,function(){
            img1.scale()
        })
</script>
<script>
        function Div(text) {
            let div = document.createElement(`div`)
            div.innerText = text
            document.body.appendChild(div)
            this.dom = div
        }

        Div.prototype.changeColor = function(color){
            this.dom.style.backgroundColor=color
            
        }

        Div.prototype.setFont = function(font){
            this.dom.style.fontSize=font
        }

        let img1 = new Div(`这是一个DIV`)

        let btn = document.querySelector(`button`)
        btn.addEventListener(`click`,function(){
            img1.changeColor(`red`)
            img1.setFont(`100px`)
        })
</script>