• 本周学习总结(原生+算法)


    Button

     button{
         100px;
        height: 50px;
        border-radius:25px;
        color:#000;
        border:2px solid blue;
        background-color: transparent;
      }
    

    overflow:scroll

    出现滚动条

    记忆函数

    const add = () => {
      let a = {}
      return num => {
        const result=num+10
        a[num]=result
        console.log(a)
        if (num in a) {
          return a[num]
        }else{
          return result
        }
      }
    }
    let a = add()
    console.log(a(20))
    console.log(a(10))
    

    import 和require

    import 命令是编译阶段执行的,在代码运行之前,就是意味着被导入的模块会先运行,而导入模块的文件会后运行

    require() 运行代码时候再运行

    BigInt(新的基础类型)

    BigInt 数据类型的目的是比Number 属性类型支持的范围更大的整数值,主要用于大于Number 数据类型支持的范围

    要创建BigInt ,只需在整数的尾数追加n即可

    或者BigInt("9007199254740995")

    9007199254740995n

    console.log(typeof 10n);    // → bigint
    10n==10  //true
    与`BigInt`操作数一起使用时,算术运算符应该返回`BigInt` 值,因此,除法运算符的结果会自动向下舍入到最接近的整数
    25n/10n;   // 2n
    不能对混合使用`number`和`BigInt`  操作数执行算术操作
    可以通过转化进行操作
    BigInt(10)+10n
    10+Number(10)
    

    VDOM

    VDOM就是一个数据结构

    从逻辑上vdom就是用来抽象DOM的,底层上vdom普遍实现是基于哈希表这种数据结构

    {
        type:'div',
        props:{
            name:'lucifer'
        },
        children:[{
            type:'span',
            props:{},
            children:[]
        }]    
    }
    

    所以我们从面向DOM编程,切换到面向VDOM编程,由于VDOM又是由数据驱动的,所以也就是数据驱动

    DOM dif算法

    AST

    AST(抽象语法树) 是前端编译(转义)的理论基础

    AST厉害就厉害在它本身不涉及到任何语法,因此你只要编写相应的转义规则,就可以将任何语法转义到任何语法,这就是babel,PostCSS,prettier,typescript 等的原理,除此之外,还有很多应用场景,比如编辑器

    Lodash源码分析

    _.chunk (不怎么理解)

    _.chunk(['a', 'b', 'c', 'd'], 2);
    // => [['a', 'b'], ['c', 'd']]
    
    console.log([1, 2, 3, 4].reduce((acc, val, i) => {
      return [...acc,[val]]
    },[]))
    //[[1],[2],[3],[4]]
    i%2
    输入: 0 1 2 3 4
    输出: 0 1 0 1 0
    
    const chunk = (arr, size) => {
      return arr.reduce((acc, val, index) => {
        if (index % size === 0) {
          return [...acc, [val]]
        } else {
          //[[1,2],[3,4],[5]]
          return [...acc.slice(0, -1), [...acc.slice(-1)[0], val]]
          //[[1,2],[3,4],[5,6]]
        }
      }, [])
    }
    console.log(chunk([0,1,2,3,4,5,6], 2));
    //[ [ 0, 1 ], [ 2, 3 ], [ 4, 5 ], [ 6 ] ]
    

    找到二维数组中不同的数

    let arrays = [[1, 2, 3, 4, 5], [5, 2, 10]];
    console.log(arrays.reduce((a, b) => a.filter(c => !b.includes(c))));
    //a=>[1,2,3,4,5]
    //b=>[5,2,10]
    console.log([[1, 2, 3, 4, 5], [1, 2, 4]]
      .reduce((acc, val) => {
        //return val //[1,2,4]   
        return acc //[1,2,3,4,5]
      }))
    // output: [1, 3, 4]
    

    深度降维

    const flattenDeep = (arr) => Array.isArray(arr)
      ? arr.reduce( (a, b) => a.concat(flattenDeep(b)) , [])
      : [arr]
    

    求多维数组的交集

    let arrays = [[1, 2, 3,10], [101, 1, 10], [2, 1,10]];
    console.log(arrays.reduce((acc, val) => acc.filter(item => val.includes(item))))
    

    根据数组的个数,排成一个对象

    console.log(['one', 'two', 'three'].reduce((acc, val, index, array, k = val.length) => {
      (acc[k] || (acc[k] = [])).push(val)
      return acc
    }, {}))
    //{ '3': [ 'one', 'two' ], '5': [ 'three' ] }
    

    函数式编程

    函数式编程中的函数指的是数学中的函数,而不是javascript中的函数

    纯函数就是给定输入,输出总是相同的函数

    柯里化
    const add=x=>y=>x+y
    add(1)(2)   //3
    
    const g = x => x + 20
    const f = x => x * 2
    const compose = (f, g) => x => f(g(x))
    console.log(compose(f, g)(10))  //40
    
    **bind**
    const add = (x, y, z) => x + y + z
    const plus = add.bind(null, 10)
    console.log(plus(10, 10))//30
    console.log(plus(20, 20))//50
    
    //[1, 2, 3]   =>   { 1: 1, 2: 4, 3: 9 }
    const mapObject = (arr, fn) => {
      let itemArr = arr.map(fn);
      return arr.reduce((acc, val, index) => 
        (acc[val] = itemArr[index], acc), {})
    }
    
    //求最小值,最大值
    const over=(...fns)=>(...args)=>fns.map(val=>val.apply(null,args))
    over(Math.min, Math.max)(1, 2, 3, 4)
    
    //输入(9,3)   输出 [81,6]   也就是第一个参数**2   第二个参数*2
    //简单版
    const over1 = (first, last) => [first ** 2, last * 2]
     console.log(over1(9, 3))//[81,6]
    //封装版
    const overArg=(fn,fns)=>(...args)=>args.map((val,i)=>fns[i](val))
    console.log(overArg( [x => x ** 2, x => x * 2])(4,6)) //[ 16, 12 ]
    
    //高阶函数
    //自执行函数
    (function (s) {
      return s*2
    })(2);//4
    (x => x * 2)(2);//4
    //高阶
    const add=fn=>x=>fn(x);
    add(x => x + 2)(2)//4
    

    隔行变色

      li:nth-child(2n) {
        background-color: red;
      }
      li:nth-of-type(2n-1) {
        background-color: gold;
      }
    

    超过一行省略号...

    .aaa{
        200px;
       overflow:hidden;
       white-space:nowrap;
       text-overflow:ellipsis;
    }
    

    伪元素

    .aaa{
        position:relative;
    }
    .aaa:after{
        content:'';
       	position:absolute;
        right:0;
        bottom:0;
    }
    

    undefined

    未为变量赋值时默认值为undefined

    当访问未初始化的变量,不存在的对象属性,不存在的数组元素等时,将接收一个undefined的值

    1138

    U

    D

    L

    R

    ! 几个

    输入:target = "leet"
    输出:"DDR!UURRR!!DDD!"
    
    输入:target = "code"
    输出:"RR!DDRR!UUL!R!"
    
    const alphabet = target => {
      let res = '';
      let x = 0,
        y = 0;
      for (let item of target) {
        let x1 = Math.floor((item.charCodeAt() - 97) / 5),
          y1 = (item.charCodeAt() - 97) % 5;
        //当前的位置l  x轴的位置  c是y轴的位置
        let l = x1 - x;
        c = y1 - y;
          //记得x轴=>c   y轴=>l
        /*上*/
        if (l < 0) {
          for (let i = 0; i < -l; i++) {
            res += 'U'
          }
        }
        /*下*/
        if (l > 0) {
          for (let i = 0; i < l; i++) {
            res += 'D'
          }
        }
        /*左*/
        if (c < 0) {
          for (let i = 0; i < -c; i++) {
            res += 'L'
          }
        }
        /*右*/
        if (c > 0) {
          for (let i = 0; i < c; i++) {
            res += 'R'
          }
        }
        res += '!';
        x = x1, y = y1;
    
      }
      return res
    }
    console.log(alphabet('kb'))
    

    LeetCode1128

    求多米诺骨牌的数量

    dominoes[i] = [a, b] 和 dominoes[j] = [c, d]

    等价的前提是 ac 且 bd,或是 ad 且 bc

    也就是[1,2],[2,1]或者是[1,2],[1,2]

    例如

    输入[[1, 2], [2, 1], [3, 4], [3, 4],[6,5], [5, 6]]

    输出 3

    var numEquivDominoPairs = function (dominoes) {
      let arr = Array.from({ length: 100 }, v => 0);
      let res = 0;
      for (let item of dominoes) {
        //*10,是为了 [2,5]或者[3,4]不是相等的
        res += arr[Math.min(item[0], item[1])*10 + Math.max(item[0], item[1])]++
      }
      return res;
    };
    console.log(numEquivDominoPairs([[1, 2], [2, 1], [3, 4],[2,5],[6,5], [5, 6]]))
    //3
    

    724寻找数组的中心索引

    我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。

    如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。

    左边的和等于右边的和
    简化为: 总和-右边的和-中间数=左边的和
    const Solution = nums => {
      let sum = 0;
      leftSum = 0;
      sum = nums.reduce((acc, val) => acc + val)
      for (let i = 0; i < nums.length; i++) {
        if (leftSum == sum - leftSum - nums[i]) {
          return i;
        }
        leftSum += nums[i]
      }
      return -1
    }
    console.log(Solution([1,2,3,6,2,3,1]))
    
    

    747 至少是其他数字两倍的最大数

    在一个给定的数组nums中,总是存在一个最大元素 。

    查找数组中最大元素是否至少是数组中每个其他数字的两倍

    如果是,返回最大的索引,否则返回-1

    实例1

    输入:nums=[3,6,1,0]

    输出:1

    思路:6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1

    实例2

    输入: nums = [1, 2, 3, 4]
    输出: -1
    解释: 4没有超过3的两倍大, 所以我们返回 -1.

    找到最大和第二大的元素,看最大的是不是第二大的2倍,若不是直接返回-1,在数组中找到索引
    const Solution = nums => {
      if (nums.length == 1) {
        return 0
      }
      //最大值
      let max = 0;
      //第二大的值
      let second = 0;
      //索引
      let index = 0;
      for (let i = 0; i < nums.length; i++) {
        if (max < nums[i]) {
          max = nums[i]
          index = i;
        }
      }
      for (let item of nums) {
        if (item < max && second < item) {
          second = item
        }
      }
      console.log(max, second)
      if (second * 2 <= max) {
        return index
      }
      return -1
    }
    console.log(Solution([1, 2, 3, 4, 9]))
    

    283 移动零

    把一个数组里所有的0都移到后面,不能改变非零数的相对位置关系,而且不能拷贝额外的数组。

    举例

    输入:[0,1,0,3,5,0]

    输出:[1,3,5,0,0,0]

    //双指针
    const Solution = nums => {
      let index = 0;
      for (let i = 0; i < nums.length; i++) {
        if (nums[i] != 0) {
          nums[index++] = nums[i]
        }
      }
      while (index < nums.length) {
        nums[index++] = 0;
      }
      return nums
    }
    console.log(Solution([0, 1, 1, 2, 3, 0, 0, 21]))
    //[ 1, 1, 2, 3, 21, 0, 0, 0 ]
    

    LeetCode 389找不同

    输入:
    s = "abcd"
    t = "abcde"

    输出:

    'e'

    运算性质:
    A^B^B=A
    
    //第一种位运算
    const findThe = (s, t) => {
      let t1 = 0
      let index = 0;
      while (index < s.length) {
        t1 ^= s.charCodeAt(index)
        index++
      }
      let b = 0;
      while (b < t.length) {
        t1 ^= t.charCodeAt(b)
        b++
      }
      return String.fromCharCode(t1)
    }
    console.log(findThe('abc', 'bc'))
    //'a'
    
    //桶排序
    const findThe = (s, t) => {
      const ans = Array.from({ length: 26 }, v => 0)
      let i = 0,
        j = 0,
        k = 0;
      while (i < s.length) {
        ans[s.charCodeAt(i) - 97]++
        i++
      }
      while (j < t.length) {
        ans[t.charCodeAt(j) - 97]++
        j++
      }
      while (k < ans.length) {
        if (ans[k] == 1) {
         return String.fromCharCode(k + 97)
        }
        k++
      }
      return -1
    
    }
    

    leetCode 455分发饼干

    你的目标是尽可能满足越多数量的孩子,并输出这个最大数值

    实例一

    输入:[1,2,3],[1,1]

    输出:1

    解释:
    你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
    虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
    所以你应该输出1。

    实例二

    输入: [1,2], [1,2,3]

    输出: 2

    解释:
    你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
    你拥有的饼干数量和尺寸都足以让所有孩子满足。
    所以你应该输出2.

    const findCount = (g, s) => {
      g.sort()
      s.sort()
      let i = 0,
        j = 0;
      while (i < g.length && j < s.length) {
        //满足就是s[j]>=g[i]
        //如果满足,饼干j++,结束判断后换个孩子(i++)
        if (s[j] >= g[i]) {
          j++
        }
        i++
      }
      return i
    }
    console.log(findCount([1, 2], [1,2,3]))
    //满足2个孩子
    

    48 旋转矩阵

    /*
    * Given input matrix =
    [
      [1,2,3],
      [4,5,6],
      [7,8,9]
    ],
    rotate the input matrix in-place such that it becomes:
    [
      [7,4,1],
      [8,5,2],
      [9,6,3]
    ]
    */
    const rotate = (matrix) => {
      let arr = Array.from({ length: matrix.length }, v => [])
      for (let i = 0; i < matrix.length; i++) {
        for (let j = 0; j < matrix[i].length; j++) {
          arr[i][j]=matrix[matrix.length-1-j][i]
        }
      }
      return arr
    }
    let array1=[
        [1,2,3],
        [4,5,6],
        [7,8,9]
      ];
    console.log(rotate(array1))
    
    

    136 只出现一次的数

    [1, 2, 3, 1, 1, 10, 2].filter(
      (val, index, array) =>
        array.indexOf(val) == array.lastIndexOf(val))
    
    
    // 5^5=0  0^5=5
    var singleNumber = function (nums) {
      let result=0;
      for (let i = 0; i < nums.length; i++) {
        result^=nums[i]
      }
      return result
    };
    
    const singleNumber = function (nums) {
      let set = new Set();
      for (let i = 0; i < nums.length; i++) {
        if (set.has(nums[i])) {
          set.delete(nums[i])
        } else {
          set.add(nums[i])
        }
      }
      return Array.from(set)
    };
    
    //2*(去重的数组的和)-原数组的和
    //只考虑重复一次
    const singleNumber = function (nums) {
      let set = new Set(nums);
      return Array.from(set).reduce((acc,val)=>acc+val)*2-nums.reduce((acc,val)=>acc+val)
    };
    console.log(singleNumber([1, 2, 4,1,2]))
    

    79单词搜索

    给定一个二维网格和一个单词,找出该单词是否存在于网格中。

    单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

    board =
    [
      ['A','B','C','E'],
      ['S','F','C','S'],
      ['A','D','E','E']
    ]
    
    给定 word = "ABCCED", 返回 true.
    给定 word = "SEE", 返回 true.
    给定 word = "ABCB", 返回 false.
    
    [
        ['A', 'B', 'C'],
        ['D', 'A', 'A'], 
        ['G', 'C', 'D']
    ]
    'ABCAD'
    // 要走的数组,给定的路径数组
    //原路径,新路径
    const exist = (thePath, newPath) => {
      for (let y = 0; y < thePath.length; y++) {
        for (let x = 0; x < thePath[0].length; x++) {
          //d是走了几步
          if (finds(thePath, newPath, y, x, d=0)) {
            return true
          }
        }
      }
    return false
    }
    const finds = (thePath, newPath, y, x, d) => {
      //走的长度等于要走的数组的长度
      if (d == newPath.length) return true;
      //x,y不能大于数据的长度,也不能少于0
      if (y < 0 || x < 0 || y == thePath.length || x == thePath.length) return fasle;
      //开始比较
      if (thePath[y][x] != newPath[d]) return false;
      //记录走过上一步的位置
      let temp = thePath[y][x]
      thePath[y][x]='*'
      //是否可以走下一步
      /*右*/
      let exist = finds(thePath, newPath, y, x + 1, d + 1)
        /*左*/
        || finds(thePath, newPath, y, x - 1, d + 1)
        /*下*/
        || finds(thePath, newPath, y + 1, x, d + 1)
        /*上*/
        || finds(thePath, newPath, y - 1, x, d + 1)
      //移动到上一步走的位置
      thePath[y][x]=temp
      return exist
    }
    console.log(exist([['A', 'B', 'C'], ['D', 'A', 'A'], ['G', 'C', 'D']], 'ABC'))
    
    

    41 缺失的第一个正数

    给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

    示例 1:

    输入: [1,2,0]
    输出: 3
    

    示例 2:

    输入: [3,4,-1,1]
    输出: 2
    

    示例 3:

    输入: [7,8,9,11,12]
    输出: 1
    
    const Solution=nums=>{
      let i=1;
      while (i) {
        if (nums.indexOf(i) < 0) {
          return i
        }
        i++
      }
    }
    
    var firstMissingPositive = function (nums) {
      let set = new Set();
      for (let i = 0; i < nums.length; i++) {
        //nums[i]>=1  且  每个数小于数组的个数
        if (nums[i] >= 1 && nums[i] <= nums.length) {
          set.add(nums[i])
        }
      }
      for (let i = 1; i <= nums.length; i++) {
        if (!set.has(i)) {
          return i
        }
      }
      return nums.length + 1
    };
    console.log(firstMissingPositive([3, 4, -1, 1]))
    
  • 相关阅读:
    前端常用设计模式和工作中应用场景思考
    webpack从零开始打造react项目(更新中...)
    操作系统-进程
    go语言web框架-如何使用gin教程+react实现web项目
    JavaScript逗号运算符的用法
    react的生命周期和使用
    在Vue项目中使用wangEditor
    TypeScript实现axios
    SpringBoot整合邮件发送(thymeleaf和freemarker)
    SpringBoot整合RabbitMQ
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/11291862.html
Copyright © 2020-2023  润新知