JS高级浅研究

91 阅读6分钟

箭头函数

  1. // 定义一个箭头函数,没有形参,没有返回值,2行实际业务
    const func = () => {
        console.log(123);
        console.log(456);
    };
    
  2. //   没有形参,返回值,业务一行代码,大括号省略
    const func1 = () => console.log(123);
    
    
  3. // 只有一个形参,没有返回值,业务一行代码
    const func2 = (num) => console.log(num);
    
  4. // 两个或者多个参数(括号不能省略),没有返回值,业务只有一行代码
    const func3 = (a, b) => console.log(a, b);
    
  5. // 没有形参,有返回值,业务两行代码
    const func4 = () => {
        let a = 1;
        return a + 100;
    };
    
    
  6. // 没有形参,有返回值,业务一行代码,不用写return单词
    const func5 = () => 100 + 100;
    const func6 = () => {
        return 100 + 200;
    };
    
    
  7. // return可以用小括号代替,下面是返回对象
    const func7 = () => ({a:123})
    

    伪数组转数组方法

    [...array]

    <body>
        <ul>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
        <script>
            let lis=document.querySelectorAll("li")
            lis=[...lis]
            console.log(lis.every);
        </script>
    </body>
    

常用数组方法

forEach()

数组里面的每个元素都执行一次回调函数

const arr = ["a", "b", "c", "d"];

arr.forEach(function (value, index) {
	console.log(`值是${value}, 索引是${index}`);
});

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

map()

根据原数组,返回新数组

  1. const arr = ["a", "b", "c"];
    const newArr = arr.map((value) => value + 1);
    console.log(newArr);
    
    
  2. // 数据驱动视图渲染
    const textArr=["刘德华","郭富城","张学友","黎明"]
    const newTextArr=textArr.map(value=>`<div>${value}</div>`)
    // 数组转换成字符串
    const html=newTextArr.join("")
    console.log(html);
    document.body.innerHTML=html
    
    

every()

要求数组的每一个元素都符合要求,every才返回true

**注意:**空数组调用every(),也会返回true

const arr=[1,2,3,4]
const result=arr.every(value=>{
    if(value<5){
        return true
    }else{
        return false
    }
})
console.log(result);

const arr=[1,2,3,4]
const result = arr.every((value) => value < 5);
// 只写一行代码,省略if判断

使用

场景:商品全选,每一个商品选中,全选框再自动勾选

some()

要求数组中至少有一个符合需求

**注意:**空数组调用some(),返回false,因为没有一个符合条件

const arr = [1, 2, 3, 4, 5];
const result = arr.some((value) => value < 6);
console.log(result);


filter()

过滤,过滤出满足条件的数据,返回新的数组

const arr = [1, 2, 3, 4, 5];
const newArr = arr.filter((value) => value > 3);
console.log(newArr);

数组去重

some()

满足相等条件,返回true,停止运行

<input type="text" id="txt" />
<ul class="txtList"></ul>
<script>
    const txt = document.querySelector("#txt");
    const txtList = document.querySelector(".txtList");
    let txtArr = [];
    txt.addEventListener("keyup", function (e) {
        if (e.key === "Enter") {
            const result = txtArr.some((value) => value === this.value);
            if (result === true) {
                console.log("stop");
                this.value = "";
            } else {
                txtArr.push(this.value);
                render();
                this.value = "";
            }
        }
    });
    function render() {
        const newArr = txtArr.map((value) => `<li>${value}</li>`);
        const html = newArr.join("");
        txtList.innerHTML = html;
    }
</script>

filter()

过滤数组

<input type="text" id="txt" />
    <ul class="txtList"></ul>
    <script>
      const txt = document.querySelector("#txt");
      const txtList = document.querySelector(".txtList");
      let txtArr = [];
      txt.addEventListener("keyup", function (e) {
        if (e.key === "Enter") {
          const newArr = txtArr.filter((value) => value !== this.value);
          txtArr=newArr
          txtArr.push(this.value);
          render();
          this.value=""
        }
      });
      function render() {
        const newArr = txtArr.map((value) => `<li>${value}</li>`);
        const html = newArr.join("");
        txtList.innerHTML = html;
      }
</script>

设置isHas

isHas默认flase,遍历数组,找到设置true表示找到,打断遍历,接着判断isHas,true则什么也不做,反之正常运行

<input type="text" id="txt" />
<ul class="txtList"></ul>
<script>
      const txt = document.querySelector("#txt");
      const txtList = document.querySelector(".txtList");
      let txtArr = [];
      txt.addEventListener("keyup", function (e) {
        if (e.key === "Enter") {
          let isHas = false;
          for (let index = 0; index < txtArr.length; index++) {
            if (this.value === txtArr[index]) {
              // 找到重复数据,打断循环
              isHas = true;
              break;
              this.value = "";
            }
          }
          if (isHas) {
            console.log("stop");
          } else {
            txtArr.push(this.value);
            render();
            this.value = "";
          }
        }
      });
      function render() {
        const newArr = txtArr.map((value) => `<li>${value}</li>`);
        const html = newArr.join("");
        txtList.innerHTML = html;
      }
</script>

设置i = -1

i默认-1,遍历找到相同内容,将i设置为对应下标,splice删除内容后,再重新添加进入数组遍历渲染

<!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>找到重复的删除下标,再重新添加渲染</title>
  </head>
  <body>
    <input type="text" id="txt" />
    <ul class="txtList"></ul>
    <script>
      const txt = document.querySelector("#txt");
      const txtList = document.querySelector(".txtList");
      let txtArr = [];
      txt.addEventListener("keyup", function (e) {
        if (e.key === "Enter") {
          let i = -1; //默认表示未找到
          for (let index = 0; index < txtArr.length; index++) {
            // 找到对应下标内容相等,打断循环,索引赋给i
            if (txtArr[index] === this.value) {
              i = index;
              break;
            }
          }
          if (i === -1) {
            // 什么也不干
          } else {
            // 删除对应下标
            txtArr.splice(i, 1);
          }
          txtArr.push(this.value);
          render();
          this.value = "";
        }
      });
      function render() {
        const newArr = txtArr.map((value) => `<li>${value}</li>`);
        const html = newArr.join("");
        txtList.innerHTML = html;
      }
    </script>
  </body>
</html>

set**对象

  • ES6推出

  • 主要功能:数组去重

  • set是一个对象,不是数组

  • 使用过程,考虑对象-数组 数组-对象互相转换的方法

  • 如果有初始数组需要去重,创建set对象时把数组传给set对象

    • const beforeArr=[1,2,'a','b']
      const set = new Set(beforeArr)
      
  • 往set对象添加数据的方法

    • set.add(1)
      set.add(2)
      set.add(2) // 有重复数据时,内部自动过滤
      
  • 案例去重

    • <input type="text" id="txt" />
      <ul class="txtList"></ul>
      <script>
        const txt = document.querySelector("#txt");
        const txtList = document.querySelector(".txtList");
        let txtArr = ['a','b'];
        render()
      	txt.addEventListener("keyup", function (e) {
      		if (e.key === "Enter") {
      			txtArr.push(this.value)
            const set=new Set(txtArr)
            txtArr=[...set]
            render()
            this.value=""
      		}
        });
        function render() {
          const newArr = txtArr.map((value) => `<li>${value}</li>`);
          const html = newArr.join("");
          txtList.innerHTML = html;
        }
      </script>
      

其他方法

  • indexOf
  • find
  • findIndex
  • includes
  • set
  • every

面向对象

分析对象

对象最主要特征:属性、行为

创建对象的方式

  • 字面量——创建方便,但不利于维护

    • // 字面量,创建简单,不方便维护
              const obj1={name:'monkey',action:'run'}
              const obj2={name:'bajie',action:'run'}
              const obj3={name:'wujing',action:'run'}
              const obj4={name:'tangseng',action:'run'}
              const obj5={name:'pusa',action:'run'}
      
      
  • 工厂函数——方便维护,但不能运用继承

    •     function creatPerson(name,age,sex) {
              return {
                  username:name,
                  age:age,
                  sex:sex
              }
          }
          const obj=creatPerson('wukong','12','man')
        
      
      
  • 构造函数

    • 可以方便的创建对象

    • 拥有血缘关系

    • 还有后续更多的优势

    • 构造函数的方法通过调用外部的方法来解决性能问题,也方便代码维护(但是也会很容易污染全局变量)

    •     // 构造函数
          // 声明一个函数,创建对象的方法叫做构造函数
          function creatObject(name,age) {
              this.name=name,
              this.age=age
          }
          // 实例——创建出来的对象叫做实例
          const obj1=new creatObject('小谭','12')
          console.log(obj1);
        
      
      
    • new一个对象的底层原理

      • 开辟新空间
      • 将新创建的对象关联到对象构造函数中的this
      • 为对象赋值
      • 将创建好的对象的地址返回
    • prototype(原型对象)

      • 优势:解决性能问题,污染全局变量问题

      • 原型对象相当于DNA

      • 修改了DNA,通过构造函数创建的实例都会一起发生修改

      • DNA新增一些东西,对应实例一样会新增

      • function CreatePerson(name, age) {
            (this.name = name), (this.age = age);
        }
        CreatePerson.prototype.say = function () {
            console.log("hello");
        };
        const obj=new CreatePerson("xiaomi",12)
        console.log(obj.say());
        // 小结 原型对象-构造函数 一般情况 
        // 构造函数内只放属性 name 、age、color、height
        // 对应原型上 都是放 方法 = 函数
        
        

原型-继承

xxx.call()借调,调用

  • 儿子调用父亲的属性行为

    • const car={
          name:"装甲车",
          add:function(str){
              console.log(this.name+" 说话了" + str);
          }
      }
      car.add()
      const person={
          name:"person"
      }
      car.add.call(person,"hahah")
      
  • 儿子调用父亲属性

    • function Person(name,age,height) {
          // person的属性名修改,student属性名也随之修改
          this.username=name,
              this.age=age,
              this.height=height
      }
      function Student(name,age,height,color) {
          // call()一定要先传入借调使用者this
          Person.call(this,name,age,height)
          this.color=color
      }
      const person=new Person("xiaoming",12,180)
      const student=new Student("小米",20,180,"red")
      console.log(person);
      console.log(student);
      
  • 儿子调用父亲原型对象方法

    • 儿子的原型.say() = 父亲的原型.say()

    • function Person(name,age){
          this.name=name,
              this.age=age
      }
      Person.prototype.say=function () {
          console.log(this.name,this.age);
      }
      function Student(name,age){
          Person.call(this,name,age)
      }
      Student.prototype.say=Person.prototype.say
      const person=new Person("xiaomi",90)
      const student=new Person("ray",19)
      person.say()
      student.say()
      
  • 代码封装调用小案例

    • // 需求:封装父亲代码,儿子调用创建div,另一个儿子调用创建img
      // 创建构造函数
      function Element(tagName) {
          const dom=document.createElement(tagName)
          this.dom=dom
      }
      // 原型对象-插入方法
      Element.prototype.append=function (appendPosition){
          document.querySelector(appendPosition).appendChild(this.dom)
      }
      // 调用父亲
      function ElementDiv(tagName,text) {
          Element.call(this,tagName)
          this.dom.innerText=text
      }
      ElementDiv.prototype.append=Element.prototype.append
      function ElementImg(tagName,src) {
          Element.call(this,tagName)
          this.dom.src=src
      }
      ElementImg.prototype.append=Element.prototype.append
      // 实例 一定要加new
      const div=new ElementDiv("div","div的内容")
      div.append("body")
      const img=new ElementImg("img","../day01/wallpaper/Kha'Zix.jpg")
      img.append("div")
      

ES6

函数参数默认值

function show(msg = "默认值", word = "默认词") {
    console.log(msg, word);
}
show();
show("传入第一个实参");
show("传入第一个实参", "传入第二个实参");

对象简写

let username = "悟空";
let age = 12;
function say() {
    console.log("say");
}
const obj = {
    username,
    age,
    say,
    move() {
        console.log("move");
    },
};

console.log(obj);

解构

(主要用在对象和数组)

数组解构

// 数组解构
const arr=[4,5]
const [a,b]=arr
console.log(a,b);

对象解构

// 对象解构
const person={
    username:"越前龙马",
    age:14,
    height:180
}
const {username,age,height}=person
console.log(username,age,height);

拓展-剩余-延展-运算符

...

剩余应用场景:伪数组转换真数组

const [a,b,...c]=[1,2,3,4,5,6,7,8,9,10]
    console.log(c);
    const {e,...d}={a:1,b:1,c:10}
    console.log(d);
    function calc(...args) {
    console.log(args);
}
calc(1,2,3,4,5)

延展应用场景:计算最大值最小值,对象的复用

// 计算最大值最小值
unction calc(...args){
	console.log(Math.max(...args))
}
calc(1,2,20,3)
//   对象复用, 对象是引用类型不能直接赋值给新对象,需要另辟新空间
const obj={
    name:"猴子",
    height:500
}
const newObj={...obj}
newObj.color="pink"
newObj.name="八戒"
console.log(obj,newObj);

es6面向对象

构造函数和方法分开定义

// 新语法 类class
class Person{
  // 构造函数
  constructor (name){
    // console.log("开始创建对象啦");
    this.name=name
  }
  // 方法在构造函数外面定义
  say(){
  	console.log(this.name," 被调用");
  }

}
const person=new Person("悟空")
const person1=new Person("悟空1")
console.log(person);
person.say()
console.log(person1);
person1.say()

方法

三种写法(最简便写法也就是性能最优写法)

<script>
        class Person{
            say1(){
                console.log("say1");
            }
            say3=function(){
                console.log("say3");
            }
            say2=()=>{
                console.log("say2");
            }
        }
        const p1=new Person()
        const p2=new Person()

			// 只有say1的内存地址是一样的,说明性能最优
        console.log(p1.say1===p2.say1);
        console.log(p1.say2===p2.say2);
        console.log(p1.say3===p2.say3);
    </script>

继承

  • extends——仅有extends只会继承类方法

  • super()——继承构造函数

  • // 新语法 类class
          class Person {
            // 构造函数
            constructor(name) {
              // console.log("开始创建对象啦");
              this.name = name;
            }
            // 方法在构造函数外面定义
            say() {
              console.log(this.name, " 被调用");
            }
            skill() {
              console.log(this.name, " 打人啦");
            }
          }
    
          //   extends 只是继承方法,要继承构造函数还要加上super()
          class Student extends Person {
            constructor(name, color) {
              super(name), (this.color = color);
            }
          }
          const student=new Student("我是学生")
          student.skill()
          console.log(student);
    

原型链

万物皆对象,而对象的原型方法也是可以修改和新增的

const div=document.querySelector("div")
console.dir(div)
Array.prototype.show=function (){
  console.log(123);
}

bind,call,apply改变this指向

  • 大部分情况,对于普通函数,this等于这个函数的调用者(例外-bind、call、apply)
  • 大部分情况,对于箭头函数,this等于window
    • 箭头函数和this一起用,要慎用
    • 例外:(面向对象用法-this则指向实例本身)
const obj={
  name:"武松",
  skill(){
  	console.log(this.name+" 打虎");
	}
}
const person={
  name:"大郎"
}
// call
obj.skill.call(person)
// apply
obj.skill.apply(person)
// bind
const func=obj.skill.bind(person)
func()

call传参

const obj={
  name:"武松",
  skill(a,b){
    console.log(this.name+" 打虎",a,b);
  }
}
const person={
  name:"大郎"
}
// call
obj.skill.call(person,1,2)

bind传参

容易理解

// bind
const func=obj.skill.bind(person)
func(1,2)

apply传参

第一个参数如果是null,则表示默认指向

// apply
obj.skill.apply(person,[1,2])
obj.skill.apply(person,...arr)

拓展

旧的获取最大值写法

const arr=[1,2,3]
console.log(Math.max.apply(null,arr))

新的获取最大值写法(解构数组)

const arr=[1,2,3]
console.log(Math.max(...arr))