• 前端面试题题库


    http://www.qdfuns.com/notes/24610/01b6dcaafaf78da4a2b79ebcbca9e4b6.html

    https://www.cnblogs.com/En-summerGarden/p/6973522.html

     https://www.nowcoder.com/discuss/85670

    css基础面试题: https://juejin.im/entry/5ad2d3bff265da237a4d75dd

    JavaScript 练习题库:https://scriptoj.com/

    1、完成 extname 函数,它会接受一个文件名作为参数,你需要返回它的扩展名。

    例如,输入 emoji.png,返回 .png

    const extname = (filename) => {
      /* TODO 要考虑输入是'hello' 和 '.hello'的情况时输出都是'' */
     let arr = filename.split('.');
     return (arr.length > 1 && arr[0] !== '') ? '.' + arr[arr.length-1] : '';
     
    }

     2、

    观察者模式在前端开发中非常常用,我们经常用的事件就是观察者模式的一种体现。它对我们解耦模块、开发基于消息的业务起着非常重要的作用。Node.js 原生自带 EventEmitter 模块,可见它的重要性。

    完成 EventEmitter 模块,它是一个类,它的实例具有以下几个方法:onemitoff

    • on(eventName, func):监听 eventName 事件,事件触发的时候调用 func 函数。
    • emit(eventName, arg1, arg2, arg3...):触发 eventName 事件,并且把参数 arg1, arg2, arg3... 传给事件处理函数。
    • off(eventName, func):停止监听某个事件。

    使用例子:

    var EventEmitter = require('events').EventEmitter;
    const emitter = new EventEmitter()
    const sayHi = (name) => console.log(`Hello ${name}`)
    const sayHi2 = (name) => console.log(`Good night, ${name}`)
    
    emitter.on('hi', sayHi)
    emitter.on('hi', sayHi2)
    emitter.emit('hi', 'ScriptOJ')
    // => Hello ScriptOJ
    // => Good night, ScriptOJ
    
    emitter.off('hi', sayHi)
    emitter.emit('hi', 'ScriptOJ')
    // => Good night, ScriptOJ
    
    const emitter2 = new EventEmitter()
    emitter2.on('hi', (name, age) => {
      console.log(`I am ${name}, and I am ${age} years old`)
    })
    emitter2.emit('hi', 'Jerry', 12)
    // => I am Jerry, and I am 12 years old

    JavaScript

    /*
    *浏览器端模拟EventEmitter的实现,拓展了部分功能,添加了定制实践促发的次数的功
    *能, 使用方式和其他的EventEmiiter类似。 
    */
    (function (window, undefined) {  
        'use strict';  
        /*构造函数*/  
        var EventEmitter = function() {  
            this.events = {};//保存事务,存储结构为{'eventName1':[{listener:function触发的函数, time:触发的次数}], 'eventName2':[],}  
        };  
          
        EventEmitter.prototype.once = function(evt, listener) {  
             return this.addListener(evt, listener, 0);  
        };  
        /*获取所有的事务*/  
        EventEmitter.prototype.getEvents = function() {  
            return this.events || (this.events = {});  
        }  
        /*获取某个实践的所有触发函数*/  
        EventEmitter.prototype.getListeners = function(evt) {  
             var events = this.getEvents();  
             return events[evt] || (events[evt] = []);  
        };  
        /** 
          注册实践触发函数 
          evet:事件名称 
          listener:事件监听函数 
          time:可选,选择可以触发的次数,-1表示无数次,默认为-1 
        **/  
        EventEmitter.prototype.on = function(evt, listener, time) {  
            time = typeof(time) == 'number' ? time : -1;  
            time = time >= -1 ? time : -1;   
            var listeners = this.getListeners(evt);  
            var listenerWrapper = {  
                listener:listener,  
                time:time,  
            };  
            listeners.push(listenerWrapper);  
              
            return this;  
        };  
        /*addListener 和on 同义 */  
        EventEmitter.prototype.addListener = EventEmitter.prototype.on;  
        /*移除事件的所有监听函数*/  
        EventEmitter.prototype.off = function(evt) {  
            var events = this.getEvents();  
            events[evt] = [];  
        };  
        EventEmitter.prototype.removeEvent = EventEmitter.prototype.off;  
          
        /** 
          会删除同一事件中的所有listener 
        **/  
        EventEmitter.prototype.removeListener = function(evt, listener) {  
            var listeners = this.getListeners(evt);  
            for(var i=0; i<listeners.length; i++) {  
                if(listeners[i].listener == listener) {  
                    delete listeners[i];  
                }  
            }  
        };  
        /** 
          触发事件 
        **/  
        EventEmitter.prototype.trigger = function(evt, args) {  
            var listeners = this.getListeners(evt);  
            for(var i=0; i<listeners.length; i++){  
                var listener = listeners[i];  
                if(listener.time != -1) {  
                    listener.time--;  
                }  
                if (listener.time == 0) {  
                    this.removeListener(evt, listener.listener);//可以同步或异步执行  
                }  
                listener.listener.apply(this, args || []);  
            }  
        };  
        EventEmitter.prototype.fire = EventEmitter.prototype.trigger;  
        /** 
          触发事件 
        **/  
        EventEmitter.prototype.emit = function(evt) {  
            var args = Array.prototype.slice.call(arguments, 1);  
            return this.trigger(evt, args);  
        };  
          
        EventEmitter.inherit = function(target) {  
              
            if(typeof(target.prototype) == 'undefined') {  
                throw 'target:' + target + 'must have prototype';  
            }  
            var souPto = EventEmitter.prototype;  
            var tarPto = target.prototype;  
            for(var key in souPto) {  
                tarPto[key] = souPto[key];  
            }  
            return target;  
        };  
          
        window.EventEmitter = EventEmitter;  
          
    })(window); 

     找出最大子数组(js实现)

    有长度为n 的数组,其元素都是int型整数(有正有负)。在连续的子数组中找到其和为最大值的数组。

    如 [1, -2, 3, 10, -4, 7, 2, -5]的最大子数组为[3, 10, -4, 7, 2]

    方法1: 暴力解决

    直接使用循环,时间复杂度O(n^3)

    function maxSubArray(arr) {
        const len = arr.length;
        if (len<=1) {
            return arr
        }
        let sum = arr[0];
        let x_pos=0;
        let y_pos=0;
        for(let i=0;i<len-1;i++){
            for(let j=i+1;j<len;j++){
                let tmp = 0;
                for(let k=i;k<=j;k++){
                    tmp+=arr[k]
                }
                if (tmp>sum) {
                    sum=tmp;
                    x_pos=i;
                    y_pos=j;
                }
            }
        }
        // console.log("sum is",sum)
        return arr.slice(x_pos,y_pos+1)
    }

    方法2:逻辑分析

    因为有正有负,所以子数组的和的最大值肯定为正值(哪怕该子数组只有一个正数)。(思考下:如果数组中全是负数时呢?)

    其次可以得出:最大子数组的第一个元素、最后一个元素肯定为正值。

    开始遍历数组,记录两个变量current_sum+=arr[i],max_sum=0,一旦current_sum<0是不是current_sum中记录的连续元素就绝对不可能成为最大子数组?所以此时重置current_sum=0开始从下一个元素记录其连续片段的和。继续与max_sum比较即可。

    在循环过程中只要current_sum>max_sum,就设置max_sum =current_sum

    这样只需要一个遍历,即可完成对最大子数组和的计算。时间复杂度O(n).

    function maxSubArray(arr) {
        const len=arr.length;
        if (len<=1) {
            return arr
        }
        //left_pos,right_pos 记录最大子数组的位置信息
        let left_pos=0;
        let right_pos=0;
        let maxSum=0;
        let curSum=0;
        for(let i=0;i<len;i++){
            curSum+=arr[i]
            if (curSum>maxSum) {
                maxSum=curSum
                right_pos=i
            }
            if (curSum<0) {
                curSum=0
                left_pos=i+1
            }
        }
        let maxArr=arr.slice(left_pos,right_pos+1)
        console.log("sub arr is ",maxArr)
        return maxSum
    }

    如果考虑到数组中全是负数的情况呢?

    上面是根据current_sum是否小于0来决定current_sum是是否开始记录新的子数组的和。在数组向后扫描时,针对a[i+1]有两种选择:

    • 加入current_sum
    • 作为新子数组中的第一项。

    那么判断条件是什么呢?是current_sum +a[i]a[i]的值的比较。如果a[i]加上前面的和却更小,那就将其作为新数组的第一项,同时更新记录数组位置的值。

    for(let i=0;i<len;i++){
        if (curSum+arr[i]<arr[i]) {
            curSum=arr[i]
            left_pos=i
        }else{
            curSum=curSum+arr[i]
        }
        if(curSum>maxSum){
            maxSum=curSum
            right_pos=i
        }
    }
  • 相关阅读:
    NHibernate官方文档中文版--拦截器和事件(Interceptors and events)
    NHibernate官方文档中文版——批量插入(Batch inserts)
    NHibernate官方文档中文版-框架架构(Architecture)
    NHibernate官方文档中文版--ISessionFactory的配置(ISessionFactory Configuration)
    ConcurrentDictionary的key判断存在的两种方式,用错了慢100倍
    树莓派3B+,我要跑.NET Core
    C# .NET Framework4.0环境下使用async/await语法,以及其中的需要注意的地方。
    C# 利用结构体对固定格式数据进行解析
    简单工厂模式
    正则表达式替换指定格式内容,实现类似String的Format方法(用扩展方法)
  • 原文地址:https://www.cnblogs.com/xuepei/p/8056912.html
Copyright © 2020-2023  润新知