• 学习JavaScript进阶


    JavaScript进阶

    循环语句

    • for循环

      // 类似python中的for i in range(20)
      
      for(let i=0; i<20; i++){
          console.log(i)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • while循环

      const MAX_TIMES = 20;
      let cur = 0
      while (cur < MAX_TIMES){
          cur++;
          console.log(cur)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    • do while

      do {
          cur ++;
          console.log(cur);
      }while (cur < MAX_TIMES)
      
      • 1
      • 2
      • 3
      • 4
      • while循环有什么区别?

        do while一定先执行一遍代码块的表达式;

    • for in

      遍历对象的属性

      let myObj = {a: 1, b:2, c:3, d:4}
      for (let e in myObj){
          console.log(e, myObj[e]);
      }
      
      • 1
      • 2
      • 3
      • 4
    • for of

      遍历可迭代对象的元素

      let myArray = [1, 2, 3, 4, 5]
      for (let e of myArray){
          console.log(e);
      }
      
      • 1
      • 2
      • 3
      • 4
      • 常见的可迭代对象有哪些?

        • Array

        • Set

        • Map

        • String

        • arguments

          function foo(a, b){
              console.log(arguments);
          }
          
          foo(1, 2)
          
          • 1
          • 2
          • 3
          • 4
          • 5
    • forEach

      let myArray = [1, 2, 3, 4, 5]
      myArray.forEach(function (e){
          console.log(e * e);
      })
      
      • 1
      • 2
      • 3
      • 4

    条件语句

    • 一个简单的判断语句

      for(let i=0; i<100; i++){
          if (i%2===0){
              console.log("偶数", i)
          }else if(i < 0){
              console.log("负数不判断")
          }else{
              console.log("奇数", i)
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 逻辑运算符

      • ==

        对比操作数是否相同, 操作数会尝试进行类型转换后的比较, 不推荐做为比较符号.

        '1' == 1
        > true
        
        false == 0
        > true
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • ===

        严格等于

        '1' === 1
        > false
        
        false === 0
        > false
        
        • 1
        • 2
        • 3
        • 4
        • 5
      • !

        逻辑取反

        for(let i=0; i<100; i++){
        	// 注意运算优先级的问题, 不能写成!i%2
            if (!(i%2)){
                console.log("偶数", i)
            }else if(i < 0){
                console.log("负数不判断")
            }else{
                console.log("奇数", i)
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
      • &&||

        • &&表示AND
        • ||表示OR

    选择语句

    • switch case

      function foo(arg){
          switch (arg){
              case 'a':
                  console.log(arg, 1);
                  break;
              case 'b':
                  console.log(arg, 2);
                  break;
              case 'c':
                  console.log(arg, 3);
                  break;
              default:
                  console.log('default')
          }
      }
      
      foo('e')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

    异常处理

    try{
    	表达式
    }catch (e){
    	表达式
    }finally{
    	表达式
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 一个基本的异常捕获

      function foo(){
          try{
              throw TypeError('test');
          }catch (e){
              console.log('Error', e);
          }finally{
              console.log('Done!')
          }
      }
      
      foo()
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 处理具体的异常

      处理具体的异常, 只能通过if条件语句来进行类型判断

      function foo(){
          try{
              throw TypeError('test');
          }catch (e){
              if (e instanceof TypeError){
                  console.log("TypeError")
              }else{
                  console.log('Error', e);
              }
          }finally{
              console.log('Done!')
          }
      }
      
      foo()
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • 抛出异常

      throw可以抛出任意对象, 让catch去捕获

      function foo(){
          try{
              throw {'a':1};
          }catch (e){
              if (e instanceof TypeError){
                  console.log("TypeError")
              }else{
                  console.log('Error', e);
              }
          }finally{
              console.log('Done!')
          }
      }
      
      foo()
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    对象和类

    js当中其实没有明确的类的概念, js当中的类只是创建对象的模板. 它的本质还是一个特殊的函数

    class关键字只是一层封装了原型链的语法糖, 但是方便我们理解.

    • 声明类

      class Rectangle {
          constructor(height, width) {
              this.name = 'ractangle';
              this.height = height;
              this.width = width;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 创建对象/实例

      let rectangle = new Rectangle(2, 5);
      console.log(rectangle)
      
      • 1
      • 2
    • 类方法

      • 构造方法

        constructor是一种用来创建和初始化class创建的对象;

      • 实例方法

        class Rectangle {
            constructor(height, width) {
                this.name = 'ractangle';
                this.height = height;
                this.width = width;
            }
        
            getArea(){
                return this.height * this.width;
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
      • 静态方法

            static staticMethod(){
                console.log("calling static method")
            }
        
        • 1
        • 2
        • 3
      • gettersetter

            get area(){
                return this.getArea()
            }
        
            set area(value){
                this._value = value
            }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
    • 类继承

       class Square extends Rectangle {
          constructor(a) {
              super(a, a);
              this.name = 'square'
          }
      }
      
      let suqare = new Square(10)
      console.log(suqare.area)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 私有方法和属性

      通过#来声明一个私有方法或者属性, 只允许类内部调用

      class Square extends Rectangle {
          // 私有属性需要事先进行声明
          #new_name
          constructor(a) {
              super(a, a);
              this.#new_name = 'square'
          }
      
          get new_name(){
              return this.#getName()
          }
      
          #getName(){
              return this.#new_name
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

    构造函数和this

    在JS中通过构造函数来创建对象的场景更多, 而不是通过class

    • 声明一个构造函数

      function Rectangle(height, width){
          this.name = 'rectangle';
          this.width = width;
          this.height = height;
      
          this.getArea = function (){
              return this.height * this.width
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
    • 创建对象/实例

      let rectangle = new Rectangle(10, 2)
      console.log(rectangle.getArea())  
      
      • 1
      • 2
    • 通过call方法继承

      第一个参数是要绑定的对象, 其他参数代表调用函数的参数.

      call方法将Rectangle下的属性和方法绑定到this上去

      这里的this指代的就是实例化的square对象

      function Square(a){
          Rectangle.call(this, a, a);
          this.name = 'square'
      }
      
      • 1
      • 2
      • 3
      • 4
      • apply

        call方法几乎没有区别, 只是传入的参数的方式不同

        function Square(a){
            Rectangle.apply(this, [a, a]);
            this.name = 'square'
        }
        
        • 1
        • 2
        • 3
        • 4
    • this

      不能简单地认为this指向的就是实例对象.

      可以简单地认为谁调用该函数, this就指向谁.

    原型链式继承

    在传统面向对象编程中, 我们继承的实现方式都是在创建实例时, 将类中定义的属性和方法都复制到实例中去.

    但是JS中继承是在对象/实例和它的构造器之间创立一个链接, 这个链接就是__proto__

    • 原型链

      js中每个构造函数拥有一个原型对象prototype, 对象从原型继承方法和属性. 而当前对象继承的原型对象可能也有原型, 这样就形成了一条原型链

      square.__proto__.__proto__.__proto__
      
      • 1
      • __proto__prototype的区别?

        __proto__是每个对象/实例都有的属性, 而prototype只是构造函数的属性.

    • 原型链式继承

      当前对象/实例square找不到getArea方法时, 会继续在原型链中寻找.

      function Square(a){
          this.height = a;
          this.width = a;
          this.name = 'square'
      }
      
      Square.prototype = new Rectangle()
      let square = new Square(10)
      console.log(square.getArea())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

    异步JS

    JS引擎只是浏览器中的一个线程, 所以在JS当中没有线程和进程的概念.JS的高性能是通过一个基于事件循环的异步并发模型来完成.

    • 事件循环

      在页面环境中, 我们移动鼠标, 点击页面元素或者执行一段JS, 都可以认为当前是一个消息. 当前的消息会被丢进一个无限循环的消息队列当中, 每一个消息都关联着用来处理这个消息的回调函数

      document.addEventListener("click", function(e){console.log(e)})
      
      • 1
      • 事件循环的伪代码

        while(queue.waitForMessage()){
        	queue.processNextMessage();
        }
        
        • 1
        • 2
        • 3
      • 消息的执行

        • JS在执行同步消息任务时, 会执行至完成.
        • JS在执行异步消息任务时, 遇到异步操作, 会将该消息丢回消息队列, 等待下一次调度执行.

    callbacks(异步回调)

    最常见于浏览器的监听事件, 本质就是将回调函数做为参数传递给后台执行的其他函数, 其他函数在执行完毕后自动调用回调函数

    document.addEventListener("click", function(e){console.log(e)})
    
    • 1
    • 回调地狱

      // 银行转账的伪代码
      transferAccount(cash,
          dealCash(cash, function(cash_status){
              authAccount(cash_status, function(order){
                  transferStart(order, function(status){
                      sendSMS(status)
                  }, transferExceptionCallback)
              }, authExceptionCallback)
          }, cashExceptionCallback)
      )
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    Promise

    Promise是一个对象, 它代表了一个异步操作的最终完成或者失败的结果.

    img

    • 声明一个简单的promise对象

      let promiseOjb = new Promise((resolve, reject) => {
          setTimeout(() => {
              resolve("success");
              reject("failed");
          }, 3*1000)
      }).then(result => {console.log("result => ", result)})
      
      console.log(promiseOjb)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • promise的状态

      • pending

        初始状态, 表示未接收到结果

      • fullfill

        已兑现, 表示操作成功完成

      • reject

        已拒绝, 表示操作失败

    • 在使用promise时, 需要注意以下约定

      • 回调函数时在当前事件循环结束后自动调用的;
      • 通过then添加的回调函数不管异步操作是否成功都会执行;
      • 通过调用多次then可以添加多个回调函数, 他们按插入顺序依次执行, 这个方式就叫做链式调用;
    • promise中处理异常

      • 声明一个简单的xhr请求

        function xhrRequest(url){
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open('GET', url);
                xhr.onload = function(){resolve(xhr.responseText)};
                xhr.onerror = () => reject(xhr.status);
                xhr.send()
            }).then(result=>{console.log("SUCCESS", result)})
                .catch(error=>{console.log("FAILURE", error)})
        }
        
        xhrRequest("http://www.baidu.com")
        xhrRequest("https://www.baidu.com")
        xhrRequest("https://www.baidu.com/asdfasdf/")
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 当前环境下, 客户端请求到达了服务端, 服务端也正常地返回了结果. 那么不管状态码是200还是404, 都算是一次成功的请求, 所以结果由then回调进行处理, 而不是catch. 如果有需要可以自己通过状态码判断后执行不同的流程.
      • 链式调用

        function xhrRequest(url){
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest();
                xhr.open('GET', url);
                xhr.onload = function(){resolve(xhr.responseText)};
                xhr.onerror = () => reject(xhr.status);
                xhr.send()
            }).then(result=>{console.log("SUCCESS", result); return result})
                .then(result=>{console.log("SUCCES 2", result)})
                .catch(error=>{console.log("FAILURE", error)})
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 不管当前链式调用有多长, 异常都会进到catch回调函数当中. catch也可以进行链式调用, 但是一般一个函数只有一个catch回调函数.

    async/await

    async本质就是将函数转换为promise

    • 通过asyncawait等待完成结果

      function xhrRequest(url){
          return new Promise((resolve, reject) => {
              const xhr = new XMLHttpRequest();
              xhr.open('GET', url);
              xhr.onload = function(){resolve(xhr.responseText)};
              xhr.onerror = () => reject(xhr.status);
              xhr.send()
          })
      }
      
      async function requestBaidu(url){
          let result = await xhrRequest(url);
          console.log("DONE!", result)
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
    • 异常处理

      function xhrRequest(url){
          return new Promise((resolve, reject) => {
              const xhr = new XMLHttpRequest();
              xhr.open('GET', url);
              xhr.onload = function(){resolve(xhr.responseText)};
              xhr.onerror = () => reject(xhr.status);
              xhr.send()
          })
      }
      
      async function requestBaidu(url){
          try{
              let result = await xhrRequest(url);
              console.log("DONE!", result)
          }catch (e){
              console.log("FAILURE", e)
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
  • 相关阅读:
    【每日一题Day49】LC1805字符串中不同整数的数目 | 双指针+哈希表
    Go简单实现协程池
    继承需要记忆的知识点
    VideoPlayerWithOpenCVForUnityExample
    xsser工具使用教程
    docker 跨平台构建镜像
    交换机与路由技术-31-扩展ACL
    ABC-Index-(dp枚举方式优化)
    MapStruct复制对象详细介绍
    【VIO】第1讲 IMU 传感器
  • 原文地址:https://blog.csdn.net/m0_57713054/article/details/128070599