zoukankan      html  css  js  c++  java
  • js(二)

    • call,apply,bind

    主要用于改变this指向的 1.call格式:函数名.call(上下文环境,参数)

      说明:
      
         上下文环境:就是应用函数的作用域范围
         参数:是以逗号分隔的参数列表
         
         例如:getMsg.call(obj,'微信小程序','Angular');
     
     特点:1.改变this指向,2.函数被执行了
     
     2. apply格式:函数名.apply(上下文环境,参数)
     
        说明:
         上下文环境:就是应用函数的作用域范围
         参数:是用数组形式传递的参数列表
         
         例如:getMsg.apply(obj,['微信小程序111','Angular222']);
         
     特点:同call的特点
     
     3. bind格式:函数名.bind(上下文环境,参数)
     
       bind传参调用:
       
       getMsg.bind(obj,'微信小程序','Angular')()
       getMsg.bind(obj)('微信小程序','Angular')
     
     
     特点:1.改变this指向,2.返回调用函数本身,函数没有被执行
     
       回顾一下React中的事件绑定:<div onClick={this.play.bind(this)}>
       
      
     
     二、说一下call和apply的实现原理?
     
     > 记住:函数由Function构造器实例化
     
     > 平时创建一个函数:
     >
     > 1.函数声明
     >
     > function Fn() {
     >
     > }
     >
     > 2. 函数表达式
     >
     >     var Fn=function() {
     >
     >
     >     }
     >
     > 3. 用new的方式创建一个函数
     >
     >     var Fn=new Function('函数参数','函数执行体'')
     
     
    
     eval:可以将内部的字符串解析成代码或表达式去执行
     例如:
     eval('1+2')
     3
     eval('alert("1906A")')
     
     参考官方文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
    
     call实现原理,模拟call的实现:
     
     //用JS原生模拟call
     
     Function.prototype.call2=function(context) {
     
        var ctx=context || window;
     
        //将函数临时添加到对象上 
        ctx.fn=this;  //其中this代码要调用的函数
     
     
       //处理参数接收问题,arguments
       var args=[];
       for(var i=1,len=arguments.length;i<len;i++) {
           //将获取的每个参数压入数组中
           args.push('arguments['+i+']');  
       }
     
       //最后得到: args[arguments[0],arguments[1],arguments[2]]
     
     
        //执行对象上的函数,eval,用于执行字符串代码的
        var result=eval('ctx.fn('+args+')')  //ctx.fn(args)
        
        //最后删除掉这个函数
        delete ctx.fn
     
       return result;
        
     }
    
     
     apply实现原理,模拟apply实现:
     
     Function.prototype.apply2=function(context,arr) {
     
        var ctx=context || window;
     
        //将函数临时添加到对象上 
        ctx.fn=this;  //其中this代码要调用的函数
     
       //对是否有arr进行处理
       if(!arr) {
           ctx.fn();
       }else {
     
         //处理参数接收问题,arguments
         var args=[];
         for(var i=1,len=arr.length;i<len;i++) {
             //将获取的每个参数压入数组中
             args.push('arguments['+i+']');  
         }
     
         //最后得到: args[arguments[0],arguments[1],arguments[2]]
     
         //执行对象上的函数,eval,用于执行字符串代码的
         var result=eval('ctx.fn('+args+')')  //ctx.fn(args)
     
       }
        //最后删除掉这个函数
        delete ctx.fn
     
       return result;
        
     }
    
     
     三、防抖和节流实现原理?
    
        1. 防抖和节流解决什么问题?
    
           解决页面高频触发或向后端连续请求的优化逻辑问题 例如:搜索,滚动加载
           
           键盘:onkeydown(键盘按下),onkeyup(键盘抬起)
           鼠标:onmousemove(鼠标移动)
           浏览器事件:onresize(改变窗口尺寸),onscroll(滚动事件)
    
     
     2. 防抖:
    
         生活比喻:比如电脑屏保,电梯的开关
         防抖:即在固定n秒间隔内,不会执行代码逻辑,除非n秒内有事件触发,则会再延长n秒,直到n秒没有触发的事件,则在n秒后执行代码逻辑
         
         代码实现思路:
         
         1.主要利用定时器实现
         2.考虑this指向问题
         3.考虑事件对象是否使用 事件对象属于事件处理函数的参数
         
         //防抖函数具体实现
           /*
           * { function }func:代表对哪个高频函数进行防抖
           * { number } wait:代表防抖的时间间隔
           */
          function debounce(func,wait) {
               var timeout;
               return function() {
                   var _this=this;
                   var args=arguments;
                   clearTimeout(timeout)
                   timeout=setTimeout(function() {
                       func.apply(_this,args)
                   },wait)
         
               }
           }
    
     
     3. 节流
     
         生活比喻:每天有规律的时间学习,吃饭,跑步,不会因为杂事儿所打乱,类似闹钟是有规律的
         节流:固定的时间节点,执行固定的代码逻辑
     
         > **时间戳实现节流**
     
         
          //节流函数
           /*
           * { function }func:代表对哪个高频函数进行节流
           * { number } wait:代表节流的时间间隔
           * 节流有两种实现方式:时间戳方式,定时器方式
           */
           function throttle(func,wait) {
               var _this;
               var args;
               var previous=0; //记录历史时间戳
         
               return function() {
                   var now=+new Date();  //生成一个当前的时间戳
                   args=arguments;
                   _this=this;
         
                  //用当前时间now减去历史时间previous大于wait,就会执行事件处理函数,并且更新历史时间
                   if(now-previous>wait) {
                       //执行事件处理函数
                       func.apply(_this,args)
                       //更新历史时间戳
                       previous=now;
                   }
               }
           }
    
     
         > **定时器实现节流**
         
          //节流函数
           /*
           * { function }func:代表对哪个高频函数进行节流
           * { number } wait:代表节流的时间间隔
           * 节流有两种实现方式:时间戳方式,定时器方式
           */
           function throttle(func,wait) {
              var timeout;
              var args;
              var _this;
              
               return function() {
                   _this=this;
                   args=arguments;
                 if(!timeout) {
                     timeout=setTimeout(function() {
                         func.apply(_this,args)
                         timeout=null;
         
                     },wait)
                     
                 }
         
                 
               }
           }
    
     
         语言组织:
     
            功能:就是代表能用!
     
            性能:就是代表好用!
     
    
     四、new的实例原理:
     
     面试官可能会这样问:
      1.new一个构造函数时,中间发生了什么?
      2.或者new一个构造函数,中间执行了哪些步骤?
      
      答:
      第一步:创建一个临时对象obj
      第二步:获取构造函数赋值给Constructor
      第三步:将obj的原型指向Constructor的原型,目的可以让实例化对象找到构造器原型上的方法
      第四步:让Constructor属性作用于obj上,从而可以操作this.xxx的实例属性
      第五步:返回临时对象obj
      
      
      封装的new代码如下:
      
     function new1() {
        // 创建一个临时对象
        var obj={};
       //获取构造函数赋值给Constructor
       var Constructor=[].shift.apply(arguments)
       //然后arguments中的值只能除第一个值之外的参数了
       //将obj的原型指向Constructor的原型,目的可以让实例化对象找到构造器原型上的方法
       obj.__proto__=Constructor.prototype
       
       //让Constructor属性作用于obj上,从而可以操作this.xxx的实例属性
       Constructor.apply(obj,arguments)
     
       //返回obj
       return obj;
     }
  • 相关阅读:
    免费云盘,为什么不用?
    把握linux内核设计思想系列
    volley基本使用方法
    金朝阳——软件測试试题11道题目分享
    可编辑ztree节点的增删改功能图标控制---已解决
    POJ 3370 Halloween treats 鸽巢原理 解题
    Axure RP一个专业的高速原型设计工具
    Linux内核剖析 之 进程简单介绍
    [iOS]怎样在iOS开发中切换显示语言实现国际化
    scp and tar
  • 原文地址:https://www.cnblogs.com/akby/p/13033231.html
Copyright © 2011-2022 走看看