js相关(一)

js相关(一)

 1.闭包
    定义:闭包就是能够读取其他函数内部变量的函数,将函数内部和函数外部连接起来的桥梁
    意义:能够间接的访问函数内部变量
    作用:内存常驻,隔离作用域,可以用来定义私有属性 和 私有方法
    弊端:常驻内存 会增大内存的使用量 使用不当会造成内存泄露,可以改变父函数内部变量的值

2.变量作用域

3.原型和原型链
    前者对象模版(每个对象都会在其内部初始化一个属性,就是prototype(原型))
    后者利用原型让一个引用类型继承另一个引用类型的属性和方法
    
    var A=function(){}
    A.prototype.n=1
    var b=new A()
    A.prototype={
         n:2,
         m:3
    }
    var c=new A()
    
    console.log(b.n,b.m,c.n,c.m)//多少
    答案为1,undefined,2,3。原因是b继承A,所以b.n就为1,而m在A中找不到,所以为undefined,以此类推,c继承的时候A添加了n和m,所以c.n和c.m分别是2和3
    
    var F = function () {}
    Object.prototype.a = function () {}
    Function.prototype.b = function () {}
    
    var f = new F()
    // 请问f有方法a  方法b吗
    // 或者f.a()//?f.b()//?F.a()//?F.b()//?
    
    f的__proto__指向F.prototype,F.prototype.__proto__指向Object.prototype,所以f 可以取到a方法, 由于f的原型链上没经过Function.prototype,所以取不到b方法,由于构造函数F是由  
    Function new出来的,所以F.__proto__指向Function.prototype,所以F函数可以取到b方法。
    
    new运算法的工作原理:1.创建一个新对象,这个对象继承自构造函数的prototype属性2.把上下文this指向这个新对象3.要不要返回这个新对象,用return会取代,不用就返回这个新对象

4.深拷贝和浅拷贝区别及实现
    ES6的Object.assign()方法 //先建立一个空对象{},接着把obj1中所有的属性复制过去,所以obj2会长得跟obj1一样,这时候再修改obj2.b也不会影响obj1。
        var obj1 = {name:'lily'};
        var obj2 = Object.assign({},obj1);
        obj2.name = 'bob';
        console.log(obj1.name); //lily
        console.log(obj2.name); //bob
    将对象转成字符串再转换回来 //用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
         var obj = {
            a:'hello',
            b:{
                name:'lily',
                age:21
            },
            c:[1,2,3]
        };
        var obj1 = JSON.parse(JSON.stringify(obj));
        obj1.a = 'world';
        obj1.b = {
            name:'bob',
            age:15
        };
        obj1.c = [6,7,8];
        console.log(obj.a);
        console.log(obj.b);
        console.log(obj.c);
        console.log(obj1.a);
        console.log(obj1.b);
        console.log(obj1.c);
        //不能针对函数function,无效
    递归方法实现深拷贝
        function deepClone(obj){
        //先制造一个新的数组或对象,指向一个新的空间
        var newObj = Array.isArray(obj) ? [] : {};
        //判断obj的类型
        //基本类型
        if(typeof obj != 'object'){ //是普通类型的话就直接赋值,但不能直接返回obj,那样是浅拷贝
            return newObj = obj;
        }
        //引用类型
        if(obj instanceof Array){ //是数组
            for(var i=0;i<obj.length;i++){
                newObj[i] = obj[i];
                if(typeof newObj[i] == 'object'){ //如果数组的值有对象的话,就继续递归
                    deepClone(newObj[i]);
                }
            }
        }else{ //是对象
            for(var key in obj){
            if(obj.hasOwnProperty(key)){
                if(typeof obj[key] == 'object'){ //对象中的数组和对象
                    newObj[key] = deepClone(obj[key]);  //继续递归
                }else{//对象中没有引用类型
                    newObj[key] = obj[key];
                }
            }
                }
            }
            return newObj;
        }

        var obj = {
            a:'haha',
            b:[1,2,3],
            c:function(){
                console.log('hello');
            }
        };
        var cloneObj = deepClone(obj);
        cloneObj.a = '你好';
        cloneObj.b = [6,7,8];
        cloneObj.c = function(){
            console.log('world');
        };
        console.log(obj);
        console.log(cloneObj);
        
5.防抖与节流
    限制函数的执行频次,来优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象(例如input,keyup,keydown,scroll,resize,mousemove等)
    
    函数防抖:触发完事件 n 秒内不再触发,才执行;如果n秒内事件再次被触发,则重新计算时间
        应用场景:input及window的resize、scroll事件
        function debounce(fn,delay = 100){
          // 创建一个标记用来存放定时器的返回值
          let timer = null  
          return function (){
            // 每当事件触发的时候把前一个 setTimeout清除
            if(timer) clearTimer(timer) 
            // 然后又创建一个新的 setTimeout, 这样就能保证时间间隔内如果事件持续触发,就不会执行 fn 函数
            timer = setTimeOut(() => {
              fn.apply(this,arguments)
              timer = null
            },delay)
          }
        }
    函数节流:持续触发事件,每隔一段时间,只执行一次事件(类似于技能冷却时间)
        应用场景:连续不断的触发某事件
        function throttle(fn,delay = 100){
          // 通过闭包保存一个标记,相当于一个开关
          let timer = null
          return function(){
            // 在函数开头判断标记定时器是否触发,如果有值return
            if(timer) return
            timer = setTimeOut(() => {
              fn.apply(this,arguments)
              timer = null
            },delay)
          }
        }
上一篇:《深入浅出React和Redux》(3) - Export & Import, 高阶组件


下一篇:JS实现深拷贝(双越老师)