2021-09-07

js递归方式1–100求和

// 递归
let add = function(num1,num2){
  var num = num1+num2
  if(num2+1>100){
    return num
  }else{
    return add(num,num2+1)
  }
}
add(1,2)

// 循环
let sun=0;
for(let a=0;a<=100;a++){
  sun+=a
}
console.log(sun)
// 
function sun(n) {
    if (n === 1) return 1
    return sun(n - 1) + n
}
sun(100)

数组去重

ES5

let arr = [1,2,321,1,1,3,1]
function fn(){
  let arr1=[]
  for(let a of arr){
    if(arr1.indexOf(a) === -1){
      arr1.push(a)
    }
  }
}

ES6

// 1.使用set方法
arr=[...new Set(arr)]
// 2.Array.from()能把set结构转换为数组
function dedupe(array) {
  return Array.from(new Set(array));
}

节流防抖

  • 防抖:在第一次触发事件的时候,不立即执行函数,而是给出一个期限值,比如200ms,然后在200ms内没有触发事件,那么就执行函数,如果触犯了,那么计时取消,重新开始计时
let fn=function(){
  console.log(0)
}
// 防抖函数
let debounce = function(fn,delay){
  let timer = null // 计时器
  return function(){
    if(timer){ // 如果有值,取消计时器,重新计时
      clearTimeout(timer)
      timer = setTimeout(fn, delay)
    }else{ // 没有值开始计时
      timer = setTimeout(fn, delay)
    }
  }
}
debounce(fn,1000)
  • 节流:在规定的时间内,不断的触发事件,只会最后一次触发操作
let throttle = function(fn,delay){
  let flag = true;
  return function(){
    if(flag){
      return false
    }
    flag = false
    setTimeout(()=>{
      fn()//执行函数
      flag = true
    },delay)
  }
}

大数相加

js number的取值范围是 -2^53 - 2^53

超过这个范围,会出现精度丢失的问题

let a ='3123123123111',b='1321312312311';
function sun(num1,num2){
    let arr1 = num1.split(''),arr2 = num2.split('')
    let len = Math.max(arr1.length,arr2.length)
    let arr=[]
    let temp;
    let flag=false;
    for(let a =0;a<len;a++){
        let n1 = arr1.pop()
        let n2 = arr2.pop()
        n1 = n1 ? n1 : 0
        n2 = n2 ? n2 : 0
        if(flag){
            // 有进位
            temp = parseInt(n1)+parseInt(n2)+1
        }else{
            temp = parseInt(n1)+parseInt(n2)
        }
        console.log(temp)
        // 判断是否有进位
        if(parseInt(temp / 10) > 0){
            arr.push(temp%10)
            flag = true
        }else{
            arr.push(temp)
            flag = false
        }
        // 判断最后一位是否有进位
        if(a === len-1 && flag){
            arr.push(1)
        }
    }
    // 反转数组
    return arr.reverse().join('')
}
console.log(sun(a,b))

闭包

  • 有权访问另一个函数作用域中的变量的函数;一般情况就是在一个函数中包含另一个函数

    函数的变量作用域是独立的、封闭的、外部变量是访问不了的 ,但是闭包有这个能力和权限

    1. 闭包作为一个函数存在另一个函数中
    2. 闭包可以访问到父级函数的变量,且该变量不会销毁
    function person(){
        var name = 'Timi';
        function cat(){
            console.log(name);
        }
        return cat;
    }
    var per = person();// per的值就是return后的结果,即cat函数
    per();// Timi per()就相当于cat()
    per();// Timi 同上,而且变量name没有销毁,一直存在内存中,供函数cat调用
    per();// Timi
    
  • 闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。

    var age = 18;
    function cat(){
        age++;
        console.log(age);// cat函数内输出age,该作用域没有,则向外层寻找,结果找到了,输出[19];
    }
    cat();//19
    // 如果一直掉用,会一直想加 
    cat();//20
    cat();//21
    cat();//22
    > 如果程序还有其他函数,也需要用到age的值,则会受到影响,而且全局变量还容易被人修改,比较不安全,这就是全局变量容易污染的原因,所以我们必须解决变量污染问题,那就是把变量封装到函数内,让它成为局部变量。
    
    function person(){
        var age = 18;
        function cat(){
            age++;
            console.log(age);
        }
        return cat;
    }
    person();// 19
    person();// 19
    // 每次掉用该函数,重新进入该作用域,age就会重新赋值,所有cat的值一直是19
    
    var per = person();//per相当于函数cat
    per();// 19 即cat() 这样每次调用不在经过age的初始值,这样就可以一直增加了
    per();// 20
    per();// 21
    
  • 优点:

    1. 隐藏变量,不回被全局变量污染
    2. 可以读取函数内部的变量

    缺点:

    1. 导致变量不会被垃圾机制回收,造成内存消耗
    2. 不恰当的使用闭包,造成内存消耗的问题
    • 垃圾机制:JS规定在一个函数作用域内,程序执行完以后变量就会被销毁,这样可节省内存;

      使用闭包的时候,按照作用域链的特点,闭包外面的函数不回被销毁,因为函数会一直掉用,所以会一直存在,如果闭包使用过多,会导致内存销毁

深拷贝&浅拷贝

浅拷贝
let a=[0,1,2,3,4],
    b=a;
console.log(a===b); // true
a[0]=1;
console.log(a,b);   // [1,1,2,3,4] 
// 改变a的值,b也会随着改变
  • 基本数据类型number,string,boolean,null,undefined五类

    nameval
    a1

    当b=a复制时,栈内存会新开辟一个内存,例如这样:

    nameVal
    a1
    b1
    • 现在修改b的时候,对a不会造成影响
    • 当然let a=1,b=a;虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。
  • 引用数据类型(Object类)有Object,Array,Date等。

    引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值

    当b=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值

    • 而当我们修改a中的值的时候,由于a和b指向的是同一个地址,所以b也会收到影响,这就是浅拷贝
    • 所以我们要在堆内存中也开辟一个新的内存专门为b存放值,就像基本类型那样,起步就达到深拷贝的效果了
    • 实现深拷贝
    let a=[1,2,3,4]
    b=JSON.parse(JSON.stringify(a))
    
    
    function deepCopy(obj) {
        var newObj = obj.constructor === Array ? [] : {};
        newObj.constructor = obj.constructor;
    
        if (typeof obj !== "object") {
            return;
        } else {
            for (var prop in obj) {
                console.log(prop)
                if (obj[prop].constructor === RegExp || obj[prop].constructor === Date) {
                    newObj[prop] = obj[prop];
                } else if (typeof obj[prop] === 'object') {
                    //递归
                    newObj[prop] = deepCopy(obj[prop]);
                } else {
                    newObj[prop] = obj[prop];
                }
            }
        }
        return newObj;
    }
    
    let arr = [1,23,13,13,13,13,123]
    deepCopy(arr)	
    

    $.extend( [deep ], target, object1 [, objectN ] )
    deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
    target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
    object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。

    let a=[0,1,[2,3],4],
       b=$.extend(true,[],a);
    a[0]=1;
    a[2][0]=1;
    console.log(a,b);
    

事件委托

  • 事件代理(Event Delegation),又称之为事件委托,是javascript中绑定事件的常用技巧,即吧原来需要绑定给自己的事件绑定给父元素,让父元素担任监听事件的职务,原理就是js的事件冒泡

    • 事件冒泡:当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window

    • 事件捕获:从window一直传递到自己本身

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值