JavaScript高级(一)

109 阅读5分钟

JavaScript高级(一)

一、箭头函数

1.对比函数
     // 以前写函数
      function func1(num1) {
        return num1 + 100;
      }

      // 箭头函数的时候
      // const func2 = (num1) => num1 + 100;

      // 定义一个箭头函数 没有形参 没有返回值
      const func2 = () => {
        console.log("执行业务1");
        console.log("执行业务2");
      };
2.没有形参、没有返回值、业务只有一行代码 大括号都可以省略
const func3 = () => console.log("执行业务1");
3.只有一个形参、没有返回值、业务只有一行代码
const func4 = num => console.log(num + 1);
const func4 = (num) => console.log(num + 1);
4.两个或者多个参数(括号不能省略)、没有返回值、业务只有一行代码
const func5 = (a, b) => console.log(a + b);
5.没有形参,有返回值 业务两行代码
const func6 = () => { 
  let a = 100;
  return a + 100;
};
6.没有形参、有返回值,业务一行代码
const func7 = () => 100 + 200; // 相等于 return 100+200

console.log(func7());

const button = document.querySelector("button");
button.addEventListener("click", () => {
  console.log(123321);
});

7.箭头函数-返回对象

(1)箭头函数 会认为 这个大括号 是 块级空间 符号 而不是对象的符号

const newArr1 = arr.map((value) => { name: value; }); // 这个大括号 是表示 对象的符号 还是表示 可以块级空间
// const newArr2=arr.map(value=> {
      // console.log(123) ;
      // console.log(123) ;
      // console.log(123) ;
      // return undefined
      // } );

      // // js认为 大括号是 块级空间 可以写js语句
      // {
      //   console.log(123);
      //   console.log(123);
      //   console.log(123);
      // }
      // let obj={ // js会认为大括号是 对象的符号 里面不能写 语句
      //   console.log(123);
      //   console.log(123);
      //   console.log(123);
      // }

(2)const arr = ["a", "b", "c"];返回 [ {name:"a",name:"b",name:"c"} ],思路

 const arr = ["a", "b", "c"];
// 返回 [  {name:"a",name:"b",name:"c"} ]
// const newArr=arr.map(value=>name:value );// 排除!

// const newArr=arr.map(value=>{name:value} ); // 思路正确 代码不正确

      // const newArr=arr.map(value=>{
      //   name:value
      // } ); // 思路正确 代码不正确

      // const newArr=arr.map(value=>{
      //   name:value
      //   return undefined
      // } ); // 思路正确 代码不正确

      // const newArr=arr.map(value=>{
      //   console.log(1);
      //   console.log(2);
      // } ); // 思路正确 代码不正确

      // console.log(newArr);

(3)箭头函数 的返回值 可以被省略

 const func = (num) => num + 1; // 相当于 return num+1
 const func1 = (num) => {
   return num + 1;
 }; // 这个大括号表示 块级空间


const func2 = (num) => {
        num + 1;
      }; // 会执行 num+1 但是没有返回值
      const func3 = (num) => {
        let num1 = num + 1;
        let num2 = num1 + 2;
      };
      // console.log(func3());
      const func4 = (num) => {
        return { a: 123 };
      };
      // console.log(func4());

      const func5 = (num) => {}; // 只要直接出现 大括号 就表示 块级空间 和它里面写什么代码没有关系
      // console.log(func5());
      const func6 = (num) => {
        a: 2;
      }; // 这个大括号就是对象(你的认为!! 浏览器还是一样 大括号就是块级空间)
      // console.log(func6());
      // 如果你真的看不懂 没有办法, 你先不要优雅!! 先用以前的function

(4)如果你一定要在箭头函数中想要通过省略 return的方式来 返回对象,请你加上一个小括号

const func7 = (num) => ({ a: 123 }); // => 右边加了小括号 表示想要返回 小括号里面的数据 return {a:123};
const func8 = (num) => {
  a: 123;
}; // => undefined

console.log(func7());
{
  a: 123;
} console.log(func8()); // undefined

二、数组常见方法

1.常用数组方法

1650560076538.png

2.forEach():数组每一个元素都执行一次回调函数(for循环可以通过 break来打断、 forEach不能通过break打断)
 const arr = ["a", "b", "c"];
 // 分别打印他们
 arr.forEach(function (value, index) {
   console.log(`值 是 ${value}  下标是 ${index}`);
 });

// 箭头函数写法
arr.forEach((value, index) =>console.log(`值 是 ${value}  下标是 ${index}`));

arr.forEach((value) => console.log(`值 是 ${value}`));

3.map():通过制定的函数处理数组的每一个元素,并返回处理后的数组

(1)案例

<script>
   const texts = ["刘德华", "郭德纲", "林志颖"];
   // 返回 [<div>刘德华</div>,<div>郭德纲</div>,<div>林志颖</div>]
   const newTexts = texts.map((value) => `<div>${value}</div>`);
   // console.log(newTexts)
   // 转化字符串
   const html = newTexts.join("");
   document.body.innerHTML = html;
</script>

(2)案例-捐赠管理系统-渲染部分

<script>
      // 获取tbody
      const tbody = document.querySelector("tbody");
      // 定义数据
      const arr = [
        // id:数据编号  person:捐赠人姓名   unit:捐赠单位名称  money:捐赠金额  date:捐赠日期
        {
          id: 1,
          person: "刘德化",
          unit: "壹基金",
          money: 1000,
          date: "2021-10-5",
        },
        {
          id: 2,
          person: "周杰伦",
          unit: "自然之友",
          money: 1000,
          date: "2021-01-15",
        },
        {
          id: 3,
          person: "李连杰",
          unit: "嫣然基金",
          money: 1000,
          date: "2021-06-7",
        },
      ];

      // 根据数组来渲染页面
      function render() {
        const newArr = arr.map(
          (value) => `
              <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>
         `
        );

        // 只能使用 map方法 和 数组转方式方法 join 来实现 拼接html的功能
        // 把 arr  转成(map、join 来实现功能) 变量 html 让下面的代码 (tbody.innerHTML = html;) 执行成功
        const html = newArr.join("");
        tbody.innerHTML = html;
      }

      // 根据数组数组渲染页面
      render();
    </script>
4.every():检测数值元素的每一个元素是否都符合条件

(1)案例-全选与不全选

1650561501850.png

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;
      });
    }
5.伪数组转真数组
<body>
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
    <script>
      const lis = document.querySelectorAll("li"); // 伪数组
      // const liList=domToArr(lis);
      // console.log(liList.every);

      // 转成真正的数组 一堆方式
      // const liList = [].concat(lis);
      // liList = [  lis伪数组  ]
      // liList[0] =  lis伪数组
      // liList[0].every  === lis.every  伪数组调用every
      // console.log(liList[0].every);

      // 伪数组一堆转数组的代码
      // 有很多后两天才讲到的

      // 现在先简单用一个
      // const liList=[...伪数组]
      const liList = [...lis]; // 最简单的转伪数组的方式  先这么用
    </script>
  </body>
6.some():检测数组元素中是否有元素符合指定条件
some()
function some() {
        // 检测数组,其中只要有一个元素符合条件,some返回true (every要求每一个都符合)
        const arr = [1, 3, 4, 6, 2];
        // 这个数组里面有没有元素大于6的
        const result = arr.some((value) => value > 6);
        console.log(result);
7.filter():检测数值元素,并返回符合条件所有元素的数组

(1)案例

      filter();
      function filter() {
        // 过滤, 过滤出满足条件的数据 =>新的数组
        const arr = [1, 2, 3, 4, 5, 6, 7];
        // 返回 奇数
        // const newArr = arr.filter((value) => {
        //   // 如果你return 了 true 表示当前的value你想要
        //   if (value % 2 !== 0) {
        //     // value  1 2 3 4 5 6
        //     // value%2!==0   value=[1,3,5,7]
        //     // 奇数
        //     return true;
        //   } else {
        //     return false;
        //   }
        // });

        const newArr = arr.filter((value) => value % 2 !== 0);

        console.log(newArr);
      }

(2)案例-待办列表 1650562303315.png

// 适用下方计算复选框框选时,未完成和完成的数量案例
function statistics() {
        // 未完成
        unFinishSpan.innerText =
          arr.filter((value) => !value.checked).length + " 未完成";// 未选中状态的个数
        // 已经完成
        finishA.innerText = arr.filter((value) => value.checked).length;// 选中状态的个数
      }

三、面向对象

1.什么是面向对象

一种编程行业通用的写项目级的代码的思维,引导我们如何编写高质量的代码,万物皆对象 - 看待事物的角度,(属性:数据,行为:动作(方法))。代码特点是封装和继承

2.字面量-创建对象

(1)特点:简单粗暴、不适合创建多个同样类型的对象的场景

(2)案例

const obj ={ name:"悟空",height:100,age:5000};

    <script>
      const obj1 = { username: "悟空1", tel: 123321 };
      const name1 = 123;
      const obj2 = { username: "悟空2", tel: 123322 };
      const name2 = 123;
      const obj3 = { username: "悟空3", tel: 123323 };
      const name3 = 123;
      const obj4 = { username: "悟空4", tel: 123324 };
      const name4 = 123;
      const obj5 = { name: "悟空5", tel: 123325 };
      // 好处 方便
      // 不方便维护-修改
      // 不想要name属性,修改 username
    </script>
3.工厂函数

(1)特点:容易理解 、失去血缘关系,无法简单分辨对象的特征 、后期无法实现继承

(2)案例

 <script>
      function createPerson(name, age, height) {
        return {
          // name: name,
          username: name,
          age: age,
          height: height,
        };
      }
      // 创建对象
      const obj1 = createPerson("悟空", 18, 150);
      const obj2 = createPerson("八戒", 20, 140);
      const obj3 = createPerson("龙马", 30, 190);
      console.log(obj1);
      console.log(obj2);
      console.log(obj3);

      // 优点 容易维护
      // name => username
      // 弊端 无法实现 继承的作用!
    </script>
4.构造函数

(1)特点:可以方便的创建对象、可继承、还有后续更多的优势

(2)案例

    <script>
      // 专业术语
      // 会把 createPerson 叫做 构造函数
      // 会把 createPerson 创建出来的对象 叫做 实例

      // 1 声明一个函数
      function createPerson(name, age) {
        // 2 给this赋值
        this.name = name;
        this.age = age;
        // this.color="red";
      }

      // 2 通过new的方式来创建对象
      const obj1 = new createPerson("悟空", 10);
      console.log(obj1);
      console.log(obj1.name);
      console.log(obj1.age);
    </script>
5.构造函数-性能问题(1)

(1)弊端:同一个 say 方法占据了两份内存

    function createStudent(name, age) {
      this.name = name;
      this.age = age;
      this.say = function () {
        console.log(this.name);
      }
    }

    const obj = new createStudent("悟能", 83);
    const obj1 = new createStudent("悟能1", 84);

    console.log(obj.say === obj1.say); // false  不是同一say方法 浪费了内存

(2)案例-举例理解

<script>
      function say() {
        console.log("这个是say方法");
      }

      // 构造函数的首字母大写  -  行内编码规范
      function CreatePerson(name) {
        this.name = name; // 创建了name属性
        // this.say = function () {
        //   console.log('这个是say方法');
        // };
        this.say = say; // say函数引用类型, 构造函数中的say 其实和外面的say内存地址一致的  同一个say方法
      }

      const obj1 = new CreatePerson("悟空");
      const obj2 = new CreatePerson("八戒");
      // obj1.say();
      // obj2.say();
      // 两个say的判断比较 是false 说明 两个say是在不同的内存空间上
      // 两个say 占用了两个内存空间
      // console.log(obj1.say === obj2.say); // false
      console.log(obj1.say === obj2.say); // true

      // 对于基本类型来说,=  就是复制了一份值
      //   let num = 100;
      //   let num2 = num; // 复制值  num和 num2占两给内存 各自不影响
      //   num2 = 1000;
      //   console.log(num);

      // 对于引用类似 =  其实把地址拷贝了一份给新的对象  两个数据 公用一份数据
      // let person1 = { name: '悟空' }; // person1 指向了 一个地址 0x1111 存放悟空
      // let person2 = person1; // person2也指向了person1的地址 0x1111  person1和person2 通用一个数据
      // 修改了person2 person1也会发生改变
      // person2.name = '八戒';
      // console.log(person1);

      // person2 和person1 共同指向了同一个地址
      // console.log(person1 === person2); // true

      // let o={};// 开辟了一个内存
      // let o2={};// 开辟了另外一个内存
      // console.log(o===o2);// false 两个不同的内存地址

      /* 
      构造函数想要解决 性能问题
      1 一定会把方法-函数写在构造函数的外面
      2 再通过this.say 指向外部的函数 
      
       */
    </script>
6.构造函数-性能问题(2)
 <script>
      // 构造函数的 方法 都会通过类似的这种方式 来实现 多个实例的方法共享
      function say() {
        console.log("你好");
      }
      function CreatePerson(name) {
        this.nickname = name;
        this.say = say;
      }
      // function say() {
      //   console.log("学生你好");
      // }
      // function createStudent(params) {
      // }

      const obj1 = new CreatePerson("悟空");
      const obj2 = new CreatePerson("八戒");
      console.log(obj1);
      console.log(obj2);

      console.log(obj1.say === obj2.say); // true  这个代码是合理的 优化过
      console.log(obj1.say === obj2.say); // false  不够好 性能不够好  两个say占据了两个内存

      // 函数函数 方法提取出去 这套代码
      // 优点: 方便代码维护、也解决了性能 obj1.say === obj2.say

      // 缺点:  代码不够优雅 污染了全局变量 以后不能写 say方法,很容易就覆盖()
 </script>
7.构造函数
<script>
      // 构造函数 创建不同人 大家有大家的名字, 共同一个行为 say => 说出自己的名称

      function CreatePerson(name, height) {
        this.name = name;
        this.height = height;
        // this.say = function () {
        //   // console.log(name);
        //   console.log(this.name);
        // };
      }

      CreatePerson.prototype.say = function () {
        // this 指向了实例
        // 通过this 实现了 数据传递 =访问到另外一个函数(构造函数)中的数据
        console.log(this.name, this.height); // 出错
      };

      const obj1 = new CreatePerson("八戒", 100);
      const obj2 = new CreatePerson("悟空", 150);
      obj1.say();
      obj2.say();
    </script>
8.原型对象

(1)在构造函数的原型上 存放函数,原型对象 是任何构造函数对存在的一个对象 prototype

(2)作用:解决了同一个 say 浪费 内存的问题、解决了污染全局变量的问题

(3)案例

    <script>
      function CreatePerson(name) {
        this.name = name;
      }
      // 原型对象
      // console.log(CreatePerson.prototype);
      // 在DNA上新增 东西
      CreatePerson.prototype.say = function () {
        console.log("你好");
      };
      const obj1 = new CreatePerson("悟空");
      const obj2 = new CreatePerson("八戒");
      // obj1.say();
      // obj2.say();

      function CreateStudent() {}

      CreateStudent.prototype.say = function () {
        console.log("学生你好");
      };

      // console.log(obj1.say === obj2.say);// 没有性能问题
      // 有污染全局变量的问题吗  没有
      // CreatePerson.prototype.say
      // CreateStudent.prototype.say

      // 小结 原型对象-构造函数 一般情况
      // 构造函数内只放属性 name 、age、color、height
      // 对应原型上 都是放 方法 = 函数
    </script>
9.面向对象体验
<body>
    <button class="btn1">控制图片1</button>
    <script>
      /* 
      需求: 通过 new MyImg("图片地址")  页面上就会多一个图片标签 

      1 页面上多一个图片的本质代码
        1 const img = document.createElement("img");
        2 img.src="图片地址"
        3 document.body.appendChild(img); 

      2 new的方式来创建图片 
        new MyImg 做了什么事情  => 调用了一个构造函数 MyImg


      通过 点击了按钮,控制对应的图片 放大缩小效果 

          1 css来实现放大缩小 
          2 按钮 绑定点击事件 
       */
      // const img1 = new MyImg('./images/1.png'); // 页面上多一个图片标签

      function MyImg(src) {
        const img = document.createElement("img");
        img.src = src;
        document.body.appendChild(img);

        this.dom = img; // 把图片dom元素 添加到 this对象的一个属性 dom属性上了
      }

      MyImg.prototype.scale = function () {
        // 图片放大缩小的本质是不是给图片的dom元素 添加一个class

        // 获取一下 上一个函数中的一个变量 img
        // 原型上 想要获取另外一个函数中的变量
        // console.log(this.dom);
        this.dom.classList.add("scale");
      };

      const imgModel = new MyImg("./images/gotop.png"); // 创建了一个对象

      const btn1 = document.querySelector(".btn1");

      btn1.addEventListener("click", function () {
        imgModel.scale(); // 要调用这个对象的放大缩小的方法
      });
    </script>
  </body>
10.面向对象
<body>
    <button class="btn1">控制图片1</button>
    <script>
      function MyImg(src) {
        const img = document.createElement("img");
        img.src = src;
        document.body.appendChild(img);
        this.dom = img;
      }

      MyImg.prototype.scale = function () {
        this.dom.classList.add("scale");
      };

      const imgModel1 = new MyImg("./images/gotop.png");

      const imgModel2 = new MyImg("./images/b_07.jpg");
      const imgModel3 = new MyImg("./images/b_08.jpg");

      const btn1 = document.querySelector(".btn1");

      btn1.addEventListener("click", function () {
        imgModel1.scale();
        imgModel2.scale();
        imgModel3.scale();
      });

      /* 
      小的项目  用不到所谓的面向对象
      复杂业务 面向对象技术需要(构造函数、this、原型对象)
      
       */
    </script>
  </body>
11.面向对象案例
<body>
    <button>修改颜色</button>
    <script>
      /* 
      需求:
      1   通过行代码 const divModel = new Div("这个是普通的地址");      页面中出现对应的一个div标签
      2   给按钮绑定点击事件 触发了
           divModel.changeColor("red");  这个div的背景颜色变成红色
           divModel.changeColor("yellow");  这个div的背景颜色变成黄色

      分析:
      1 Div 是一个构造函数
      2 Div 构造函数 在原型上有一个方法 changeColor


      3 const divModel = new Div("这个是普通的地址");  
        这行代码实际的作用 页面中出现一个div
        1 const div=document.createElement("div");
        2 div.innerText="文本内容"
        3 document.body.appendChild(div) 

      4 divModel.changeColor("yellow"); 这个div的背景颜色变成黄色
        ???.style.backgroundColor="yellow"
       */

      function Div(text) {
        const div = document.createElement("div");
        div.innerText = text;
        document.body.appendChild(div);
        this.dom = div;
      }
      Div.prototype.changeColor = function (color) {
        // this.dom = div;
        this.dom.style.backgroundColor = color;
      };

      Div.prototype.changSize = function (size) {
        // this.dom = div;
        this.dom.style.fontSize = size;
      };

      const button = document.querySelector("button");
      const divModel1 = new Div("这个是普通的div1");
      button.addEventListener("click", function () {
        divModel1.changeColor("red");
        // 新功能
        divModel1.changSize("100px"); // 希望div中的文字 大小变为100px
      });
    </script>
  </body>