清明自习-部分知识整理

清明自习-部分知识整理

遍历

​ 所谓遍历(Traversal),是指沿着某条搜索路线,依次对树(或图)中每个节点均做一次访问。访问结点所做的操作依赖于具体的应用问题, 具体的访问操作可能是检查节点的值、更新节点的值等。不同的遍历方式,其访问节点的顺序是不一样的。遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。当然遍历的概念也适合于多元素集合的情况,如数组。

​ 树的3种最重要的遍历方式分别称为前序遍历(根左右)、中序遍历(左根右)和后序遍历(左右根)。以这3种方式遍历一棵树时,若按访问结点的先后次序将结点排列起来,就可分别得到树中所有结点的前序列表、中序列表和后序列表。相应的结点次序分别称为结点的前序、中序和后序。

js中12中循环遍历方法
  • for循环

    • 代码示例

      let arr = [1,2,3];
      for (let i=0; i<arr.length; i++){
       console.log(i,arr[i])
      }
      // 0 1
      // 1 2
      // 2 3
      
  • for in循环

    • 代码示例

      let obj = {name:'zhou',age:'**'}
      for(let i in obj){
       console.log(i,obj[i])
      }
      // name zhou
      // age **
      
  • for of循环

    • 代码示例

      let arr = ['name','age'];
      for(let i of arr){
       console.log(i)
      }
      // name
      // age
      
  • while循环

    • 代码示例

      cars=["BMW","Volvo","Saab","Ford"];
      var i=0;
      while (cars[i])
      {
      console.log(cars[i] + "<br>")
      i++;
      };
      // BMW
      // Volvo
      // Saab
      // Ford
      
  • do while循环

    • 代码示例

      let i = 3;
      do{
       console.log(i)
       i--;
      }
      while(i>0)
      // 3
      // 2
      // 1
      
  • Array forEach方法

    • 代码示例

      let arr = [1,2,3];
      arr.forEach(function(i,index){
       console.log(i,index)
      })
      // 1 0
      // 2 1
      // 3 2
      
  • Array map方法

    • 代码示例

      let arr = [1,2,3];
      let tt = arr.map(function(i){
       console.log(i)
       return i*2;
      })
      // [2,4,6]
      
  • Array filter方法

    • 代码示例

      let arr = [1,2,3];
      let tt = arr.filter(function(i){
       return i>1;
      })
      // [2,3]
      
  • Array some方法

    • 代码示例

      let arr = [1,2,3];
      let tt = arr.some(function(i){
       return i>1;
      })
      // true
      
  • Array every方法

    • 代码示例

      let arr = [1,2,3];
      let tt = arr.every(function(i){
       return i>1;
      })
      // 检测数组中元素是否都大于1
      // false
      
  • Array reduce方法

    • 代码示例

      let arr = [1,2,3];
      let ad = arr.reduce(function(i,j){
       return i+j;
      })
      // 6
      
  • Array reduceRight方法

    • 代码示例

      let arr = [1,2,3];
      let ad = arr.reduceRight(function(i,j){
       return i+j;
      })
      // 6
      

递归

​ 程序调用自身的编程技巧称为递归( recursion)。递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。

​ 递归技巧

  1. 假设递归函数已经写好
  2. 寻找递推关系
  3. 将递推关系的结构转换为递归体
  4. 将临界条件加入到递归体中

基础递归练习:

  1. 求1-100的和

    • 代码实现
    function sum(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(parseInt(n) !== n) throw new Error("非整数!");
        if(n==0) return 0;
        return sum(n-1)+n;
    }
    
  2. 求1,3,5,7,9,……第n项的结果和前n项和,序号从0开始

    • 代码实现
    function num(n){
        if(isNaN(n)) throw new Error("参数错误");
        return 2*n+1;
    }
    function sum(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(n==0) return 1;
        return sum(n-1)+num(n);
    }
    
  3. 求2,4,6,8,10,……第n项的结果和前n项和,序号从0开始

    • 代码实现
    function num(n){
        if(isNaN(n)) throw new Error("参数错误");
        return 2*n+2;
    }
    function sum(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(n==0) return 2;
        return sum(n-1)+num(n);
    }
    
  4. 数列 1,1,2,4,7,11,16…求第 n 项,求前n项和

    • 代码实现
    function num(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(n==0) return 1;
        return num(n-1) + n - 1;
    }
    function sum(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(n==0) return 1;
        return sum(n-1) + num(n);
    }
    
  5. Fibonacci数列(斐波那契数列),求第n项

    • 代码实现
    function num(n){
        if(isNaN(n)) throw new Error("参数错误");
        if(n==0) return 0;
        if(n==1) return 1;
        return num(n-1) + num(n-2);
    }
    

高级递归练习

  1. 阶乘

    • 代码实现
    function num(n){
       if(isNaN(n)) throw new Error("参数错误");
       if(n==0) return 1;
        return num(n-1) * n;
    }
    
  2. 求幂

    • 代码实现
    function math_pow(n,m){
        if(isNaN(n)) throw new Error("参数错误");
        if(isNaN(m)) throw new Error("参数错误");
        if(n != parseInt(n) || m != parseInt(m)) throw new Error("请输入整数!");
        if(n==0) throw new Error("n不可以为0!");
        if(m==0) return 1;
        return math_pow(n,m-1) * n;
    }
    
  3. 递归方式实现深复制

    • 代码实现
    function clone(n,m){
        if((typeof n) !== "object"){
            m = n;
            return m;
        }
        if(m===undefined) m = {};
        for(var prop in n){
            if((typeof n[prop]) === "object" && n[prop] !== null){
                m[prop] = {};
                clone(n[prop],m[prop]);
            }
            else m[prop] = n[prop];
        }
        return m;
    }
    
  4. 递归实现getElementByClassName

    • 代码参考
    var arr = [];
        function byClass(node, className, arr){
            //得到传入节点的所有子节点
            var lists = node.childNodes;
            for(var i = 0;i< lists.length;i++){
                //判断是否有相同className元素
                if(arr[i],className == className){
                    arr.push(arr[i]);
                }
                //判断子节点是否还有子节点
                if(arr[i].childNodes.length > 0){
                    byClass(arr[i],className,arr);
                }
            }
        }
    //原链接:https://www.cnblogs.com/liu666/p/5745301.html
    
  5. 递归查找树结构父级

    • 代码参考
    handleSelectedNodes(tree) {
          const path = []
          function treeFindPath(tree, func, path = []) {
            if (!tree) {
              return []
            }
            for (const data of tree) {
              path.push(data)
              if (func(data)) {
                return path
              }
              if (data.children) {
                const findChildren = treeFindPath(data.children, func, path)
    
                if (findChildren.length) {
                  return findChildren
                }
              }
              path.pop()
            }
            return []
          }
          treeFindPath(tree, (data) => data.name === this.selectCategory, path)
          return path
        }
    //原链接:https://www.cnblogs.com/liu666/p/5745301.html
    
  6. 递归实现数列第1,3,5,7,9……n项的和

    • 代码实现

      	var s = 1;
      function sum(n,...arg){
          if(arguments.length < 2) throw new Error("请输入完整参数");
          n += 1;
         	if(n < arguments.length - 1) return sum(n + s,...arg) + num(n,...arg);
          return arguments[1];
      }
      function num(n,...arg){
          let arr = [];
          for(var i = 1;i<arguments.length;i++){
              arr[arr.length] = arguments[i];
          }
          return arr[n];
      }
      //存在全局变量,瑕疵很大,后面修改
      

回调函数

​ 一个回调函数,也被称为高阶函数,是一个被作为参数传递给另一个函数(在这里我们把另一个函数叫做otherFunction)的函数,回调函数在otherFunction中被调用。一个回调函数本质上是一种编程模式(为一个常见问题创建的解决方案),因此,使用回调函数也叫做回调模式。

​ 都能够将一个回调函数作为变量传递给另一个函数时,这个回调函数在包含它的函数内的某一点执行,就好像这个回调函数是在包含它的函数中定义的一样。这意味着回调函数本质上是一个闭包。正如我们所知,闭包能够进入包含它的函数的作用域,因此回调函数能获取包含它的函数中的变量,以及全局作用域中的变量。

参考链接1 参考链接2

工厂模式

工厂模式是用来创建对象的一种最常用的设计模式。我们不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂。工厂模式根据抽象程度的不同可以分为

  • 简单工厂
  • 工厂方法
  • 抽象工厂

此处涉及设计模式内容,仅作初步了解,未深入

参考链接1 参考链接2

桥接模式

1、桥接模式是一种既能把俩个对象连接在一起,又能避免二者间的强耦合的方法。通过“桥”把彼此联系起来,同时又允许他们各自独立变化

2、桥接模式主要作用就是将抽象与其实现隔离开来,以便二者独立话

参考链接1 参考链接2 参考链接3 参考链接4

数组方法重构

  • Array.push()
    • 功能:数组尾部添加一个或多个元素,并且返回数组的新长度
    • 步骤分析:
      1. 判定参数是否是数组
      2. 判定所给参数列表是否含有添加元素内容
      3. 将添加元素放入数组
      4. 返回数组新长度
function array_push(arr){
    if(arr==undefined || arr.constructor !== Array) throw new Error("错误参数"); 
    if(arguments.length===1) return arr.length;
    for(var i=1;i<arguments.length;i++){
        arr[arr.length]=arguments[i];
    }
    return arr.length; 
}
  • Array.pop()
    • 功能:删除数组尾部最后一个元素,并返回被删除元素
    • 步骤分析:
      1. 取出数组末尾元素
      2. 删除数组末尾元素
      3. 返回数组末尾元素
function array_pop(arr){
    var item=arr[arr.length-1];
    arr.length--;
    return item;
}
  • Array.unshift()
    • 功能:向数组头部插入一个或多个元素,并且返回数组的新长度
    • 步骤分析:
      1. 判断参数是否为数组
      2. 判断参数列表是否有添加元素内容
      3. 确定数组新长度
      4. 将数组原有元素后移,添加元素插入数组头部
      5. 返回数组新长度
function array_unshift(arr){
    if(arr==undefined || arr.constructor !== Array) throw new Error("错误参数"); 
    if(arguments.length===1) return arr.length;
	var len=arguments.length-1; 
    arr.length = len = len + arr.length; 
    while(len>0){
        if(len>arguments.length-1){
		arr[len-1]=arr[len-arguments.length];
       }else{
           arr[len-1]=arguments[len]; 
        }
        len--;
    }
    return arr.length;
}
  • Array.shift()
    • 功能:删除数组头部第一个元素,并且返回被删除元素
    • 步骤分析
      1. 判断数组长度,如果数组为空,返回
      2. 取出数组头部元素
      3. 所有数组元素前移一位
      4. 删除数组最后一位,改变数组长度
      5. 返回被删除元素
function array_shift(arr){
    if(arr.length===0) return;
    var item=arr[0];
    for(var i=0;i<arr.length-1;i++){
        arr[i]=arr[i+1];
    }
    arr.length--;
    return item;
}
  • Array.concat()
    • 功能:将一个数组与一个或多个元素/数组合并,产生一个新数组,不会对原数组产生影响,不填写参数时,复制原数组
    • 步骤分析:
      1. 判断参数是否是数组
      2. 声明一个空数组用于存储合并后产生的新数组
      3. 将原数组元素复制予新数组
      4. 确认参数列表长度,确定是否有添加元素内容
      5. 遍历参数列表元素,如果存在列表元素为数组,进入
      6. 遍历数组元素,将数组元素复制予新数组
      7. 返回新数组
function array_concat(arr){
    if(arr == undefined || arr.constructor !== Array) throw new Error("错参");
    var arr1=[];
    for(var i=0;i<arr.length;i++){
        arr1[arr1.length] = arr[i];
    }
    if(arguments.length === 1) return arr1;
    for(var j=1;j<arguments.length;j++){
        if(arguments[j] && arguments[j].constructor === Array){
            for(var k=0;k<arguments[j].length;k++){
                arr1[arr1.length]=arguments[j][k];
            }
        }
        else arr1[arr1.length] = arguments[j];
    }
    return arr1;
}
  • Array.join()
    • 功能:将数组元素提取转换为一个字符串,通过指定的分隔符分隔(默认为逗号),返回一个字符串,不影响原数组
    • 步骤分析
      1. 判断参数是否为数组
      2. 判断是否传入分隔符u,未传入则默认为逗号
      3. 将分隔符转换为字符串
      4. 声明一个空字符串用于存储数组元素
      5. 将数组元素存入字符串,每一个元素用分隔符分隔
      6. 返回字符串
function array_join(arr,separator){
    if(arr == undefined || arr.constructor !== Array) throw new Error("错参");
    if(separator===undefined) separator=",";
    separator = String(separator);
    var str = "";
    for(var i=0;i<arr.length-1;i++){
        str += arr[i]+separator;
    }
    str += arr[arr.length-1];
    return str;
}
  • Array.fill()
    • 功能:用传入参数填充数组指定位置,返回数组
    • 步骤分析:
      1. 判断参数是否是数组
      2. 判断是否给入填充开始位置,没有则默认从第0位开始
      3. 判断是否给入填充结束位置,没有则默认为到数组最后一位结束
      4. 将填充元素放入指定位置
      5. 返回数组
function array_fill(arr,item,start,end){
    if(arr == undefined || arr.constructor !== Array) throw new Error("错参");
    if(start === undefined) start=0;
    if(end === undefined) end=arr.length;
    for(var i=start;i<end;i++)
        arr[i]=item;
    return arr;
}
  • Array.from()
    • 功能:将列表转换为数组并返回
    • 步骤分析:
      1. 声明一个空数组用于存储列表元素
      2. 判断列表是否有长度
      3. 将列表元素放入数组
      4. 返回数组
Array.from_1=function(list){
            var arr=[]
            if(!list.length) return arr;
            for(var i=0;i<list.length;i++){
                arr[i]=list[i];
            }
            return arr;
  • Array.isArray()
    • 功能:判断参数是否是数组,返回一个布尔值
Array.isArray_1 = function(list){
    return (list && list.constructor===Array) ? true : false;
}
  • Array.splice()
    • 功能:向数组指定位置添加/删除元素,如果删除了元素,则返回被删除元素的数组
    • 步骤分析:
      1. 声明一个空数组,用于存储数组被删除元素
      2. 判断参数是否是数组
      3. 确认是否给入指定起始位置,没有则返回声明的空数组
      4. 将起始位置转换为数值类型
      5. 如果起始位置为非数值类型,则默认从第0位开始,如果起始位置小于0,则从起始位置+数组长度开始,如果仍小于0,则从第0位开始,如果起始位置大于数组长度,则起始位置等于数组长度
      6. 确认是否给入删除元素数量,没有则为从起始位置到数组元素最后一位的元素数量
      7. 将删除元素数量转换为数值类型,如果删除元素数量为非数值类型,则默认删除数量为0,如果删除数量小于0,则返回声明的空数组,如果删除数量+起始位置大于数组长度,则删除数量为从起始位置到数组元素最后一位的元素数量
      8. 遍历数组,从起始位置开始删除指定数量的元素
      9. 确认新数组长度
      10. 确认参数列表中是否有添加元素内容,有则添加至数组尾部
      11. 返回被删除元素数组
function array_splice(arr, start, deleteCount) {
    var arr1 = [];
    if (arr == undefined || arr.constructor !== Array)
        throw new Error("参数错误");
    if (start === undefined) return arr1;
    start = Number(start);
    if (isNaN(start)) start = 0;
    if (start < 0) start = start + arr.length < 0 ? 0 : start + arr.length;
    if (start > arr.length) start = arr.length;
    if (deleteCount === undefined) deleteCount = arr.length - start;
    deleteCount = Number(deleteCount);
    if (isNaN(deleteCount)) deleteCount = 0;
    if (deleteCount < 0) return arr1;
    if (deleteCount + start > arr.length) deleteCount = arr.length - start;
    for (var i = start; i < arr.length; i++) {
        if (i < deleteCount + start) arr1[arr1.length] = arr[i];
        arr[i] = arr[i + deleteCount];
    }
    arr.length -= deleteCount;
    var len = arguments.length - 3;
    var l = (arr.length += len);
    while (l > start) {
        if (l > start + len) arr[l - 1] = arr[l - len - 1];
        else arr[l - 1] = arguments[3 + (l - 1 - start)];
        l--;
    }

    return arr1;
}
  • Array.slice()
    • 功能:提取数组中指定部分元素组成新数组并返回,不影响原数组
    • 步骤分析:
      1. 声明一个空数组用于存放原数组中指定部分元素
      2. 判断起始位置的值,如果为非数值类型,则默认从第0位开始
      3. 判断结束位置的值,如果为非数值类型,则默认以最后一位结束
      4. 如果起始位置小于0,则从起始位置+数组长度开始,如果仍小于0,则从第0位开始,如果起始位置大于数组长度,则起始位置等于数组长度
      5. 如果结束位置小于0,则以结束位置+数组长度的值为结束位置,如果仍小于0,则以第0位为结束位置
      6. 取出指定部分元素予新数组
      7. 返回指定部分元素组成数组
function array_slice(arr,start,end){
    var arr1=[];
    if(isNaN(start)) start=0;
    if(isNaN(end)) end=arr.length;
    start=parseInt(start);
    end=parseInt(end);
    if(start<0) start=(start+arr.length)<0 ? 0 : start+arr.length;
    if(end<0) end=(end+arr.length)<0 ? 0 : end+arr.length;
    for(var i=start;i<end;i++){
        arr1[arr1.length]=arr[i];
    }
    return arr1;
}
  • Array.forEach()
    • 功能:遍历数组每个元素,并传给回调函数,但是对于空数组不会执行回调函数
function array_forEach(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(i in arr) fn(arr[i],i,arr);
    }
}
  • Array.map()
    • 功能:返回一个新数组,长度与原来相等,map中回调函数中使用return可以将需要的每个元素数据返回给新数组中对应的位置,但是对于空数组不会执行回调函数,不改变原数组
    • 步骤分析:
      1. 声明一个空数组用于存储需要元素
      2. 遍历原数组,将需要元素传入回调函数
      3. 返回新数组
function array_map(arr,fn){
    var arr1=[];
    for(var i=0;i<arr.length;i++){
        if(i in arr) arr1[i]=fn(arr[i],i,arr);
    }
    return arr1;
}
  • Array.some()
    • 功能:当元素中有一个满足回调函数中的条件,则返回true,并且不再继续遍历判断,否则返回false
    • 步骤分析
      1. 遍历数组,如果数组含有满足回调函数条件的元素时,返回true,否则返回false
function array_some(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(i in arr && Boolean(fn(arr[i],i,arr))) return true;
    }
    return false;
}
  • Array.every()
    • 功能:如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
    • 步骤分析:
      1. 遍历数组,如果数组含有不满足回调函数条件的元素时,返回false,否则返回true
function array_every(arr,fn){
    for(var i=0;i<arr.length;i++){
        if(i in arr && !(fn(arr[i],i,arr))) return false;
    }
    return true;
}
  • Array.filter()
    • 功能:筛选 从数组中挑选出满足条件的数据形成新数组
    • 步骤分析:
      1. 声明空数组用于存储满足条件的新数据
      2. 遍历数组,将数组元素传入回调函数,回调函数返回为ture时,将元素添加到新数组的尾部
      3. 返回新数组
function array_filter(arr,fn){
    var arr1=[];
    for(var i=0;i<arr.length;i++){
        // 回调函数返回为ture时,将元素添加到新数组的尾部
        if(i in arr && fn(arr[i],i,arr)) arr1[arr1.length]=arr[i];
    }
    return arr1;
}
  • Array.reduce()
    • 功能:归并 从数组中通过各种处理,最后返回一个结果
    • 步骤分析:
      1. 确认数组长度,确定返回值
      2. 确认初始值,确定循环开始位置
      3. 遍历数组,将元素传入回调函数
      4. 返回结果
function array_reduce(arr,fn,initValue){
    if(arr.length===0) return;
    if(arr.length===1) return arr[0];
    var index=1;//后续判断从第几个开始循环,如果有初始值则从第0个开始循环,如果没有初始值从第一个开始循环
    var value=arr[0];
    if(initValue!==undefined){
        index=0;
        value=initValue;
        // 如果初始值存在value就是初始值,如果不存在,初始值就是数组的第0项
    }
    for(;index<arr.length;index++){
       value=fn(value,arr[index],index,arr);
    }
    return value;
}
  • Array.flatMap()
    • 功能:扁平化数组,且只扁平化一层,返回一个新数组
    • 步骤分析:
      1. 声明新数组,用于存储扁平化后的新数组
      2. 遍历数组元素,判断是否元素中有数组类型元素,存在则进入,不存在则将原数组元素赋给新数组
      3. 返回新数组
function array_flatmap(arr, fn) {
    var arr1 = [];
    for (var i = 0; i < arr.length; i++) {
      var value = fn(arr[i], i, arr);
      if (value && value.constructor === Array) {
        for (var j = 0; j < value.length; j++) {
          arr1[arr1.length] = value[j];
        }
      } else {
        arr1[arr1.length] = value;
      }
    }
    return arr1;
  }
  • Array.indexOf()
    • 功能:在数组中从前向后查找某个元素的下标,如果这个元素存在,返回这个元素所在的下标,查找不到时,返回-1
    • 步骤分析:
      1. 确认是否给入开始位置,没有则默认为0
      2. 从起始位置遍历数组,查找元素
      3. 有则返回元素数组下标,无则返回-1
function array_indexOf(arr,item,formIndex){
    if(formIndex===undefined) formIndex=0;
    for(var i=formIndex;i<arr.length;i++){
        if(arr[i]===item) return i;
    }
    return -1;
}
  • Array.lastIndexOf()
    • 功能:在数组中从后向前查找某个元素的下标,如果这个元素存在,返回这个元素所在的下标,查找不到时,返回-1
    • 步骤分析:
      1. 确认是否给入开始位置,没有则默认为0
      2. 从起始位置遍历数组,查找元素
      3. 有则返回元素数组下标,无则返回-1
function array_lastIndexOf(arr,item,formIndex){
    if(formIndex===undefined) formIndex=arr.length;
    while(formIndex>=0){
        if(arr[formIndex]===item) return formIndex;
        formIndex--;
    }
    return -1;
}
  • Array.reverse()
    • 功能:颠倒数组中元素顺序
    • 步骤分析:
      1. 取中间值,左右数组元素互换
function array_reverse(arr) {
    for (var i = 0; i < parseInt(arr.length / 2); i++) {
        var temp = arr[arr.length - i - 1];
        arr[arr.length - i - 1] = arr[i];
        arr[i] = temp
    }
    return arr;
}

数组去重

解决方法:

1、for循环+Array.splice()

for(var i=0;i<arr.length;i++){
    for(var j=i+1;j<arr.length;j++){
        if(arr[i]===arr[j]){
            arr.splice(j,1);
            j--;
        }
    }
}
console.log(arr); 

2、bool标记+Array.push()

var arr=[1,2,5,3,2,4,1,2,3,5,2,1,3,2];

var arr1 = [];
for(var i=0;i<arr.length;i++){
   var bool=false;
  for(var j=0;j<arr1.length;j++){
      if(arr[i]===arr1[j]){
          bool=true;
          break;
      }
  }
  if(!bool) arr1.push(arr[i]);
}
console.log(arr); 
console.log(arr1); 

3、continue跳到标签+Array.push()

 var arr=[1,2,5,3,2,4,1,2,3,5,2,1,3,2];

    var arr1 = [];
kg: for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < arr1.length; j++) {
        if (arr[i] === arr1[j]) continue kg;
    }
    arr1.push(arr[i]);
}
console.log(arr);
console.log(arr1);

4、indexOf+Array.push()

var arr=[1,2,5,3,2,4,1,2,3,5,2,1,3,2];
var arr1 = [];

for(var i=0;i<arr.length;i++){
   if(arr1.indexOf(arr[i])<0) arr1.push(arr[i]);
}
console.log(arr1); 

排序

桶排序:
var obj = {};
for (var i = 0; i < arr.length; i++) {
    obj[arr[i]] = arr[i];
}

console.log(obj);

利用对象键名对应键值的规则,将数组中元素赋予与值相同的键名,借此完成排序

注意:不能有重复元素

冒泡排序:
for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < arr.length - 1 - i; j++) {
        if (arr[j] > arr[j + 1]) {
            var temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}

console.log(arr);

逻辑演示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gtldcz4v-1617607272423)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\冒泡排序.gif)]

选择排序:
for (var i = 0; i < arr.length - 1; i++) {
    var min = i;
    for (var j = i + 1; j < arr.length; j++) {
        if (arr[min] > arr[j]) {
            min = j;
        }
    }
    if (i !== min) {
        var temp = arr[i];
        arr[i] = arr[min];
        arr[min] = temp;
    }
}

console.log(arr);

逻辑演示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WgOfyhzu-1617607272427)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\选择排序.gif)]

快速排序:
function quickSort(elements) {
    if (elements.length <= 1) return elements;
    var pivotIndex = Math.floor(elements.length / 2);
    var pivot = elements.splice(pivotIndex, 1)[0];//将支点元素拿出来
    var left = [];
    var right = [];
    for (var i = 0; i < elements.length; i++) {
        if (elements[i] < pivot) {
            left.push(elements[i]);
        } else {
            right.push(elements[i]);
        }
    }
    return quickSort(left).concat([pivot], quickSort(right));
}

arr = quickSort(arr);
console.log(arr);

逻辑演示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jpJc3ArT-1617607272433)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\快速排序.gif)]

模糊查询

步骤分析:

  1. 获取输入内容
  2. 创建列表用于存储数组元素
  3. 通过indexof查询输入内容是否存在,用reduce返回结果
        var arr=[
            {id:1001,name:"计算器",price:26},
            {id:1002,name:"计算机",price:26},
            {id:1003,name:"飞机",price:26},
            {id:1004,name:"飞行器",price:26},
            {id:1005,name:"算盘",price:26},
            {id:1006,name:"电器",price:26},
            {id:1007,name:"电视机",price:26},
        ]
        var input=document.getElementById("input");
        var ul=document.createElement("ul");
        document.body.appendChild(ul);

        input.oninput=function(){
         ul.innerHTML=arr.reduce(function(value,item){
                if(item.name.indexOf(input.value)>-1) value+="<li>"+item.name+"</li>";
                return value;
            },"");
        }

字符串方法

  1. charAt()方法返回给定索引位置的字符,由传给方法的整数参数指定

  2. charCodeAt()方法可以查看指定码元的字符编码。这个方法返回指定索引位置的码元值,索引以整数指定。

  3. fromCharCode()方法用于根据给定的 UTF-16 码元创建字符串中的字符

  4. concat()方法用于将一个或多个字符串拼接成一个新字符串

  5. 3 个从字符串中提取子字符串的方法:

    1. slice()
    2. substr()
    3. substring()

    3个方法都返回调用它们的字符串的一个子字符串,而且都接收一或两个参数。第一个参数表示子字符串开始的位置,第二个参数表示子字符串结束的位置。对 slice()和 substring()而言,第二个参数是提取结束的位置(即该位置之前的字符会被提取出来)。对 substr()而言,第二个参数表示返回的子字符串数量。任何情况下,省略第二个参数都意味着提取到字符串末尾。与 concat()方法一样,slice()、substr()和 substring()也不会修改调用它们的字符串,而只会返回提取到的原始新字符串值。

    ​ 当某个参数是负值时,这 3 个方法的行为又有不同。比如,slice()方法将所有负值参数都当成字符串长度加上负参数值。而 substr()方法将第一个负参数值当成字符串长度加上该值,将第二个负参数值转换为 0。substring()方法会将所有负参数值都转换为 0。

  6. 在字符串中定位子字符串:

    1. indexOf()和

    2. lastIndexOf()

      这两个方法从字符串中搜索传入的字符串,并返回位置(如果没找到,则返回-1)。两者的区别在于,indexOf()方法从字符串开头开始查找子字符串,而 lastIndexOf()方法从字符串末尾开始查找子字符串。

  7. ECMAScript 6 增加了 3 个用于判断字符串中是否包含另一个字符串的方法:

    1. startsWith()

    2. endsWith()

    3. includes()

      这些方法都会从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值。它们的区别在于,startsWith()检查开始于索引 0 的匹配项,endsWith()检查开始于索引(string.length - substring.length)的匹配项,而 includes()检查整个字符串。

      ​ startsWith()和 includes()方法接收可选的第二个参数,表示开始搜索的位置。如果传入第二个参数,则意味着这两个方法会从指定位置向着字符串末尾搜索,忽略该位置之前的所有字符,endsWith()方法接收可选的第二个参数,表示应该当作字符串末尾的位置。如果不提供这个参数,那么默认就是字符串长度。

  8. ECMAScript 在所有字符串上都提供了 repeat()方法。这个方法接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果。

  9. padStart()和 padEnd()方法会复制字符串,如果小于指定长度,则在相应一边填充字符,直至满足长度条件。这两个方法的第一个参数是长度,第二个参数是可选的填充字符串,默认为空格。

  10. 大小写转换:

    1. toLowerCase()
    2. toLocaleLowerCase()
    3. toUpperCase()
    4. toLocaleUpperCase()
  11. String 类型专门为在字符串中实现模式匹配设计了几个方法。第一个就是 match()方法,这个方法本质上跟 RegExp 对象的 exec()方法相同

  12. 为简化子字符串替换操作,ECMAScript 提供了 replace()方法。

  13. localeCompare(),这个方法比较两个字符串

history与hash

hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)

location.reload();//重载,刷新当前页面
//老网页登录刷新用,现在基于AJAX不跳转

网页跳转

location.href="http://www.163.com";//href是一个可读可写的属性
location.assign("http://www.163.com");//assign是个方法,就只能执行
location.replace("http://www.163.com");//没有历史记录
History对象

History 对象包含用户(在浏览器窗口中)访问过的 URL。

History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问。

注释:没有应用于 History 对象的公开标准,不过所有浏览器都支持该对象。

回退历史记录:

history.back();

向前历史记录:

 history.forward();

history.go()

history.go(-1);//回退
history.go(1);//前进
history.go(0);//刷新页面

hash、history历史记录

css样式以及html标签初始设置参考:

 <style>
        .menu {
          list-style: none;
          margin: 0;
          padding: 0;
        }
        .menu>li {
          float: left;
          padding: 5px 20px;
          border: 1px solid #c9b8b8;
          background-color: skyblue;
          color: white;
          user-select: none;
        }
        a{
            text-decoration: none;
            color: white;
        }
        ul::after {
          content: "";
          display: block;
          height: 0;
          visibility: hidden;
          overflow: hidden;
          clear: both;
        }
        div {
          width: 1000px;
          min-height: 100px;
          background-color: antiquewhite;
        }
      </style>
<body>
    <ul class="menu">
        <li id="vegetables"><a href="#vegetables">蔬菜</a></li>
        <li id="fruit"><a href="#fruit">瓜果</a></li>
        <li id="oil"><a href="#oil">粮油</a></li>
        <li id="meat"><a href="#meat">禽肉</a></li>
      </ul>
      <div id="div1"></div>
</body>
<script>
    var list = {
        vegetables: [
          "大白菜",
          "娃娃菜",
          "油麦菜",
          "菠菜",
          "莲藕",
          "春笋",
          "韭菜",
          "胡萝卜",
          "大葱",
        ],
        fruit: [
          "苹果",
          "西瓜",
          "柚子",
          "梨",
          "香蕉",
          "樱桃",
          "草莓",
          "榴莲",
          "桃子",
          "杏",
          "橘子",
        ],
        oil: [
          "大米",
          "小米",
          "黄米",
          "黄豆",
          "绿豆",
          "红豆",
          "精面",
          "莜面",
          "花生油",
          "大豆油",
          "橄榄油",
        ],
        meat: [
          "牛肉",
          "羊肉",
          "鸡肉",
          "猪肉",
          "鸭肉",
          "鱼肉",
          "驴肉",
          "鸡蛋",
          "鸭蛋",
        ],
      };

</script>

hash:

var prev, div;
init();
function init() {
   div = document.getElementById("div1");
   window.onhashchange = hashChangeHandler;
}

function hashChangeHandler(e) {
   var id = location.hash.slice(1);
   changeTab(id);
   var data = list[id];
   renderDiv(data);
}

function renderDiv(data) {
   div.innerHTML = "<ul>" + data.reduce(function (value, item) {
       return value + "<li>" + item + "</li>";
   }, "") + "</ul>";
}

function changeTab(id) {
   if (prev) {
       prev.style.backgroundColor = "skyblue";
   }
   prev = document.getElementById(id);
   prev.style.backgroundColor = "darkblue";
}

history:

var prev, lis,div1;
init();
function init() {
  div1=document.getElementById("div1");
  lis = Array.from(document.getElementsByTagName("li"));
  lis.forEach(function (item) {
    item.onclick = clickhandler;
  });
   
  changeTab(lis[0]);
  var data=list[lis[0].id];
  renderDiv(data,lis[0].id);
  history.pushState(data,lis[0].id,"#"+lis[0].id);
  window.onpopstate=popHandler;
}

function clickhandler() {
  changeTab(this);
  var data=list[this.id];
  renderDiv(data,this.id);
  history.pushState(data,this.id,"#"+this.id);
}

function renderDiv(data,id){
  div1.innerHTML="<ul>"+data.reduce(function(value,item){
    return  value+="<li>"+item+"</li>"
  },"")+"</ul>";
 
}

function changeTab(elem) {
  if (prev) {
    prev.style.backgroundColor = "skyblue";
  }
  prev = elem;
  prev.style.backgroundColor = "darkblue";
}

function popHandler(e){
    if(!e.state) return;
    renderDiv(e.state,location.hash.slice(1));
    changeTab(document.getElementById(location.hash.slice(1)))
}
onhashchange属性

onhashchange 事件在当前 URL 的锚部分(以 ‘#’ 号为开始) 发生改变时触发。

锚部分的实例:指定当前 URL 为
http://www.example.com/test.htm#part2 - 这个 URL 中的锚部分为#part2。

你可以使用以下方式调用事件:

history.pushstate(,)

pushState()有三个参数:state对象,标题(现在是被忽略,未作处理),URL(可选)。具体细节:

· state对象 –state对象是一个JavaScript对象,它关系到由pushState()方法创建出来的新的history实体。用以存储关于你所要插入到历史 记录的条目的相关信息。State对象可以是任何Json字符串。因为firefox会使用用户的硬盘来存取state对象,这个对象的最大存储空间为640k。如果大于这个数 值,则pushState()方法会抛出一个异常。如果确实需要更多的空间来存储,请使用本地存储。

· title—firefox现在回忽略这个参数,虽然它可能将来会被使用上。而现在最安全的使用方式是传一个空字符串,以防止将来的修改。或者可以传一个简短的标题来表示state

· URL—这个参数用来传递新的history实体的URL,注意浏览器将不会在调用pushState()方法后加载这个URL。但也许会过一会尝试加载这个URL。比如在用户重启了浏览器后,新的url可以不是绝对路径。如果是相对路径,那么它会相对于现有的url。新的url必须和现有的url同域,否则pushState()将抛出异常。这个参数是选填的,如果为空,则会被置为document当前的url。

onpopstate属性

onpopstate属性是窗口上popstate事件的事件处理程序。前端的路由一般都会通过监听popstate事件来完成页面的无刷新切换

popstate每当活动历史记录条目在同一文档的两个历史记录条目之间发生变化时,就会将事件分派到窗口。如果激活的历史记录条目是通过调用history.pushState()创建的,或者受到history.replaceState()调用的影响,则该popstate事件的state属性包含历史记录项的状态对象的副本。

注意:调用history.pushState()或history.replaceState()不会触发popstate事件。该popstate事件仅通过执行浏览器操作触发,如单击“后退”按钮(或JavaScript中调用history.back()),在同一文档的两个历史记录项之间进行导航。

w.example.com/test.htm#part2 - 这个 URL 中的锚部分为#part2。

你可以使用以下方式调用事件:

history.pushstate(,)

pushState()有三个参数:state对象,标题(现在是被忽略,未作处理),URL(可选)。具体细节:

· state对象 –state对象是一个JavaScript对象,它关系到由pushState()方法创建出来的新的history实体。用以存储关于你所要插入到历史 记录的条目的相关信息。State对象可以是任何Json字符串。因为firefox会使用用户的硬盘来存取state对象,这个对象的最大存储空间为640k。如果大于这个数 值,则pushState()方法会抛出一个异常。如果确实需要更多的空间来存储,请使用本地存储。

· title—firefox现在回忽略这个参数,虽然它可能将来会被使用上。而现在最安全的使用方式是传一个空字符串,以防止将来的修改。或者可以传一个简短的标题来表示state

· URL—这个参数用来传递新的history实体的URL,注意浏览器将不会在调用pushState()方法后加载这个URL。但也许会过一会尝试加载这个URL。比如在用户重启了浏览器后,新的url可以不是绝对路径。如果是相对路径,那么它会相对于现有的url。新的url必须和现有的url同域,否则pushState()将抛出异常。这个参数是选填的,如果为空,则会被置为document当前的url。

onpopstate属性

onpopstate属性是窗口上popstate事件的事件处理程序。前端的路由一般都会通过监听popstate事件来完成页面的无刷新切换

popstate每当活动历史记录条目在同一文档的两个历史记录条目之间发生变化时,就会将事件分派到窗口。如果激活的历史记录条目是通过调用history.pushState()创建的,或者受到history.replaceState()调用的影响,则该popstate事件的state属性包含历史记录项的状态对象的副本。

注意:调用history.pushState()或history.replaceState()不会触发popstate事件。该popstate事件仅通过执行浏览器操作触发,如单击“后退”按钮(或JavaScript中调用history.back()),在同一文档的两个历史记录项之间进行导航。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟小胖砸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值