zoukankan      html  css  js  c++  java
  • 前端面试题总结

    一、JavaScript:

    1. setTimeOut准时吗?

    不一定准时,他只是把时间到了放进时间队列里

    2. JS快速打乱一个数组

    先上代码
    sort + Math.random()

    var arr=[1,2,3,4,,5,6,7,8,9,10];
    arr.sort(function(){
          return Math.random()-0.5
    })
    
    解析:
    random( )方法返回一个0-1之间的随机数,用随机数减去 0.5,可以实现随机返回一个正负数字完成乱序了
    

    3. JS 预编译

    js预编译实现过程:
    1.创建GO/AO对象
    2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
    3.将实参值和形参统一
    4.在函数体里面找函数声明,值赋予函数体

    4. JS ajax

    //步骤一:创建异步对象
        var ajax = new XMLHttpRequest();
        //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
        ajax.open('get','getStar.php?starName='+name);
        //步骤三:发送请求
        ajax.send();
        //步骤四:注册事件 onreadystatechange 状态改变就会调用
        ajax.onreadystatechange = function () {
        if (ajax.readyState==4 &&ajax.status==200) {
            //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
            console.log(ajax.responseText);//输入相应的内容
          }
        }
    

    5. 节流函数(常考点)

    /**
     * 节流:动作绑定事件,动作发生后一段时间后触发事件,
     * 在这段时间内,如果动作有发生了,则无视该动作,直到时间执行完后,才能重新触发
     * 原理:在每次函数执行前先判断是否存在定时器,存在则跳过本次执行,否则设置定时器
     */
    function throttle(fn, wait) {
      var pre = Date().now();
      return function () {
        var now = Date.now();
        if (now - prev >= wait) {
          fun.apply(this, arguments);
          pre = Date.now();
        }
      };
    }
    

    6. 防抖函数

    /**
     * 动作绑定事件,
     * 动作发生后在一定时间内触发事件,
     * 在这段时间内,如果动作发生了,则重新等待一定时间在触发事件
     *
     * 原理:在每次函数执行前先清空上一次设置的定时器
     * */
    function debounce(fn, wait) {
      var timer;
      return function () {
        if (timer) {
          clearTimeout(timer);
        }
        timer = setTimeout(() => {
          fn.apply(this, arguments);
        }, wait);
      };
    }
    

    7. JS bind 实现

     if (!Function.prototype.bind) {
            Function.prototype.bind = function () {
                var self = this,                        // 保存原函数
                context = [].shift.call(arguments), // 保存需要绑定的this上下文
                args = [].slice.call(arguments);    // 剩余的参数转为数组
                return function () {                    // 返回一个新函数
                    self.apply(context,[].concat.call(args, [].slice.call(arguments)));
                }
            }
        }
    

    8. JS map 实现

    Array.prototype.map = function () {
      var arr = this, result = [];
      var [fn, thisValue] = Array.prototype.slice.call(arguments);
      for (var i = 0; i < arr.length; i++) {
        result.push(fn.call(thisValue, arr[i], i, arr))
      }
      return result;
    }
    
    

    9. IndexOf的实现

        function ArrayIndexOf(arr,value,n){
            var i=isNaN(n)?0:n;//有第三参时
                i=(i<0)?arr.length+i:i;//第三参为负数时
            for(i;i<arr.length;i++){
                if(arr[i]===value){return i;}                   
            }return -1;
        }
    
    

    10. 懒加载

        let lazyImages = [...document.querySelectorAll('.lazy-image')]
        let inAdvance = 300 // 自定义一个高度,当距离300px到达图片时加载
        function lazyLoad() {
            lazyImages.forEach(image => {
                if (image.offsetTop < window.innerHeight + window.pageYOffset + inAdvance) { // 距离xxpx时加载图片
                    image.src = image.dataset.src
                    image.onload = () => image.classList.add('loaded')
                }
            })
        }
        lazyLoad()
        window.addEventListener('scroll', _.throttle(lazyLoad, 16)) // 用到了lodash的节流函数
        window.addEventListener('resize', _.throttle(lazyLoad, 16))
    
    

    11. JS实现promise

        class PromiseClone {
        constructor (process) {
            this.status = 'pending'
            this.msg = ''
            process(this.resolve.bind(this), this.reject.bind(this))
            return this
        }
        resolve (val) {
            this.status = 'fulfilled'
            this.msg = val
        }
        reject (err) {
            this.status = 'rejected'
            this.msg = err
        }
        then (fufilled, reject) {
            if(this.status === 'fulfilled') {
                fufilled(this.msg)
            }
            if(this.status === 'rejected') {
                reject(this.msg)
            }
        }
    
    

    12. Jsonp跨域

    function Jsonp(url, param, callback) {
      var script = document.createElement('script')
      param = {...param, callback}
      var arr = [];
      for(var key in param) {
        arr.push(`${key}=${param[key]}`)
      }
      script.src=`${url}?${arr.join('&')}`
      document.body.appendChild(script)
      window[callback] = function(data) {
        console.log(data)
        document.removeChild(script)
      }
    }
    

    13. JS 获取url参数

       function getQueryString(name) { 
        	var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); 
        	var r = window.location.search.substr(1).match(reg); 
        	if (r != null) return unescape(r[2]); return null; 
        }
        或
        export function getQueryStringByStr(data) {
            const url = data; // 获取url中"?"符后的字串
            const theRequest = {};
            if (url.indexOf('?') !== -1) {
                const str = url.substr(1);
                const strs = str.split('&');
                for (let i = 0; i < strs.length; i += 1) {
                theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]);
                }
            }
            return theRequest;
        }
    

    14. JS发布订阅模式

    vue.js是采用数据劫持结合发布者-订阅者的方式,通过object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图,
    具体步骤:
    第一步,我们首先需要给observer数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,这样当我们给对象某个值赋值,会触发setter,那么就会监听到数据.
    第二步:compile解析模板指令,将模板的所有变量转换为数据,然后初始化页面视图,将每个指令对应的节点绑定更新函数,添加监听订阅者,一但数据发生改变,收到通知,改变视图
    第三步:watcher订阅者是observer和Complie之间通信的桥梁,主要做的有:
    1.在自身实例化时往订阅器(dep)里添加自己
    2.自身必须有一个updata方法
    3.待属性变动dep.notice()通知时,能调用自身的update方法,并触发Complie中绑定的回调,完美退出
    第四步:mvvm作为数据绑定的入口,整合observe,Comple和Watcher三者,observe,来监听自己的model数据变化,Comple来解析模板指令,Watcher用来搭起observe和Cmplie之间通信的桥梁
    达到数据变化-视图更新,视图交互变化,数据model变更双向绑定效果

  • 相关阅读:
    XtraBackup2.3.3安装配置使用(innobakupex)
    MySQL主从配置问题整理
    saltstack之(十二)配置管理mount
    常用HTTP状态码和CURL 000问题
    RHEL6解决无法使用YUM源问题
    zabbix监控MySQL
    ELK-Python(三)
    解决eclipse项目下出现deployment descriptor和jax-ws web services
    【未来畅想】未来的电信通讯行业,账号密码将取代sim卡
    最新samba.tar.gz安装方法
  • 原文地址:https://www.cnblogs.com/luckyjiu9/p/13719611.html
Copyright © 2011-2022 走看看