前端面试手撕题

前端面试手撕题,第1张

目录

FED1 事件委托

FED2 数组去重

FED3 合法的URL

FED4 快速排序

FED5 全排列

FED6 instanceof

FED7 Array.map 

 FED8 Array.filter

 FED9 Array.reduce

 FED10 _objectCreate

FED11 _call函数 

FED12 Function.bind 

 FED13 实现new *** 作符

FED14 Object.freeze

 FED15 浅拷贝

浅拷贝的几种方法:

FED16 简易深拷贝

FED17 深拷贝

FED18 寄生组合式继承

JS13 类继承

JS18 继承 - 原型链继承

FED19 发布订阅模式

FED20 观察者模式


FED1 事件委托

请补全JavaScript代码,要求如下:
1. 给"ul"标签添加点击事件
2. 当点击某"li"标签时,该标签内容拼接"."符号。如:某"li"标签被点击时,该标签内容为".."
注意:
1. 必须使用DOM0级标准事件(onclick)


    
        
    
    
    	
            .
            .
            .
        

        
    
FED2 数组去重

       
FED3 合法的URL

请补全JavaScript代码,要求以Boolean的形式返回字符串参数是否为合法的URL格式。
注意:
1. 协议仅为HTTP(S)

// 补全代码
// 开始符 ^
// 协议部分http(s)://		 表示为((https|http|ftp|rtsp|mms)?:\/\/)
// 域名部分					 表示为(([A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\.)+
// 顶级域名com cn等为2-6位   表示为([a-zA-Z]{2,6})
// 端口部分					 表示为(:\d+)?, ?表示0次或1次
// 请求路径如/login			表示为 (\/.*)?
// 问号传参及哈希值如?age=1   表示为 (\?.*)?和(#.*)?
// 结束符 $
 const _isUrl = url => {
   // 补全代码
   let reg = /^((https|http|ftp|rtsp|mms)?:\/\/)(([A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\.)+([A-Za-z]{2,6})(:\d+)?(\/.*)?(\?.*)?(#.*)?$/
   return reg.test(url)
 }
FED4 快速排序

本题考点:快速排序

根据题目要求,通过快速排序实现数组参数中数字从小到大排序。快速排序的基本思想是通过分治来使一部分均比另一部分小(大)再使两部分重复该步骤而实现有序的排列。核心步骤有:

选择一个基准值(pivot)以基准值将数组分割为两部分递归分割之后的数组直到数组为空或只有一个元素为止
     const _quickSort = array => {
               if(array.length <= 1) return array;
                // 基准下标
                const flagIndex = Math.floor(array.length / 2);
                // splice返回的数组,内部是删除的元素值,获取基准元素,注意splice会改变原数组,最后需要将该元素拼接上
                const flag = array.splice(flagIndex, 1)[0];
                let left = [];
                let right = [];
                for(let i=0; i
FED5 全排列

请补全JavaScript代码,要求以数组的形式返回字符串参数的所有排列组合。
注意:
1. 字符串参数中的字符无重复且仅包含小写字母
2. 返回的排列组合数组不区分顺序

全排列:递归解法

(1)将当前元素以外的其他元素进行全排列

(2)以当前元素作为开头,拼接上得到的全排列,构成完成的全排列数组

(3)出递归的条件:字符串只要有一个长度时,直接返回

举例:

‘abc’的全排列等于 ('a'拼接上'bc'的全排列数组中的每一项) + ('b'拼接上'ac'的全排列数组的每一项) + ('c'拼接上'ab'的全排列数组的每一项)

      const _permute = string => {
               if(string.length === 1){
                   return [string];
               }
               // 全排列容器
               const res = [];
               for(let s of string) {
                    // 获取除了当前元素外的其他元素字符串
                    const otherStr = string.split('').filter(item => item!==s).join('');
                    // 递归获取其余元素字符串的递归集合,并和当前元素进行拼接
                    _permute(otherStr).forEach(str => {
                        res.push(s + str);
                    })
                }
               return res;
            }
FED6 instanceof

请补全JavaScript代码,要求以Boolean的形式返回第一个实例参数是否在第二个函数参数的原型链上。

 1、实例对象的隐式原型__proto__,等于其构造函数的显示原型prototype

利用递归 DFS终点是原型指向Null

        const _instanceof = (target, Fn) => {
                if(target.__proto__ === Fn.prototype) {
                    return true
                }
                if(Fn.prototype) {
                    _instanceof(target, Fn.prototype);
                } else {
                    return false
                }
            }
FED7 Array.map 

数组方法的简单仿写 - 哔哩哔哩

            Array.prototype._map = function(fn) {
                if(typeof fn !== 'function') return;
                let newArr = [];
                for(let i=0; i
 FED8 Array.filter

请补全JavaScript代码,要求实现Array.filter函数的功能且该新函数命名为"_filter"。

 

     Array.prototype._filter = function(callback) {
                if(typeof callback !== 'function') return;
                let newArr = [];
                for(let i=0; i
 FED9 Array.reduce

      Array.prototype._reduce = function(callback) {
                if(typeof callback !== 'function') return;
                let total = 0;
                for(let i=0; i
 FED10 _objectCreate

请补全JavaScript代码,要求实现Object.create函数的功能且该新函数命名为"_objectCreate"。

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。

Object.create(proto,[propertiesObject])

参数:proto 新创建对象的原型对象。

返回值:一个新对象,带着指定的原型对象和属性。

      const _objectCreate = proto => {
                if(typeof proto !== 'object') return;
                let Fn = function() {};
                Fn.prototype = proto; // Object.create或者_objectCreate生存的对象,其隐式原型就是入参
                return new Fn();  // 通过构造函数创建对象
            }
FED11 _call函数 

请补全JavaScript代码,要求实现Function.call函数的功能且该新函数命名为"_call"。

       Function.prototype._call = function(context, ...args) {
                // call方法接受的第一个参数必须是对象类型
                context = typeof context === 'object' ? context : window;
                // 将待执行的函数赋值给context,便于执行, 注意这里的this是一个待执行的函数,并作为属性暂时存入context对象中,
                context['fn'] = this;
                const res = context['fn'](...args);  // 执行属性函数,这时该函数就可以使用context中的属性和外部传入的参数了
                delete context['fn']; //删除暂存的属性
                return res;
            }
FED12 Function.bind 

请补全JavaScript代码,要求实现Function.bind函数的功能且该新函数命名为"_bind"。

根据题目要求,实现一个仿Function.bind功能的"Function._bind"函数,该函数会返回一个新的函数且该新函数内部通过apply修改了函数内部this指向,核心步骤有:

创建一个新this用来保存旧的this对象返回一个匿名函数,该匿名函数返回通过apply修改了指针指向的函数运算结果
            Function.prototype._bind = function(context, ...args) {
                context = typeof context === 'object' ? context : window;
                const _this = this; // 将待执行的函数缓存
                // bind返回的是一个函数,使用_this暂存this,以免闭包导致作用域不对。
                return function(...otherArgs) {
                    return _this.apply(context, args.concat(otherArgs));
                }
            }
 FED13 实现new *** 作符

请补全JavaScript代码,要求实现new *** 作符的功能。

      const _new = function(constructor) {
                let obj = {};
                obj.__proto__ = constructor.prototype;
                constructor.call(obj);
                return obj;
            }
FED14 Object.freeze

请补全JavaScript代码,要求实现Object.freeze函数的功能且该新函数命名为"_objectFreeze"

冻结后的对象不会在被修改, 不能对这个对象进行添加新属性, 不能删除已有属性, 不能修改该对象已有属性的可枚举性, 可配置性, 可写性. 此外冻结一个对象后该对象的原型也不能进行修改.  freeze()  返回和传入的参数相同

 FED15 浅拷贝

请补全JavaScript代码,要求实现一个对象参数的浅拷贝并返回拷贝之后的新对象。
注意:
1. 参数可能包含函数、正则、日期、ES6新对象

浅拷贝的几种方法:

1、Object.assign

2、扩展运算符

3、Array.prototype.concat

4、Array.prototype.slice

           const _shallowClone = target => {
                // Array,null 的 type 类型也是 object
                if(typeof target === 'object' && target !== null) {
                    // 使用构造函数名,也是实例化对象名进行第一步筛选
                    if(/^(RegExp|Date|Set|Map)$/.test(target.constructor.name)) {
                        return target;
                    }
                    // let collect = target instanceof Array  ? [] : {};
                    let collect = target.constructor === Array  ? [] : {};
                    // for in会获取继承属性,使用hasOwnProperty自身属性方法进行过滤
                    for(prop in target) {
                        if(target.hasOwnProperty(prop)) {
                            collect[prop] = target[prop]
                        }
                    }
                    return collect;
                } else {
                    return target; // 剩下的是number,bollean,string,undefined等数据类型
                }
                
            }
FED16 简易深拷贝

请补全JavaScript代码,要求实现对象参数的深拷贝并返回拷贝之后的新对象。
注意:
1. 参数对象和参数对象的每个数据项的数据类型范围仅在数组、普通对象({})、基本数据类型中]
2. 无需考虑循环引用问题

            const _sampleDeepClone = target => {
                // 复杂的对象类型
                if (target !== null && typeof target === 'object') {
                    const collect = target instanceof Array ? [] : {};
                    for(prop in target) {
                        if(target.hasOwnProperty(prop)) {
                            collect[prop] = _sampleDeepClone(target[prop]);
                        }
                    }
                    return collect;
                } else {
                    return target; // 基础类型直接返回
                }
                
            }
FED17 深拷贝

请补全JavaScript代码,要求实现对象参数的深拷贝并返回拷贝之后的新对象。
注意:
1. 需要考虑函数、正则、日期、ES6新对象
2. 需要考虑循环引用问题

FED18 寄生组合式继承

请补全JavaScript代码,要求通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。要求如下:
1. 给"Human"构造函数的原型上添加"getName"函数,该函数返回调用该函数对象的"name"属性
2. 给"Chinese"构造函数的原型上添加"getAge"函数,该函数返回调用该函数对象的"age"属性

written-examination/JS的几种继承.js at master · SUNNERCMS/written-examination · GitHub
组合继承核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

根据题目要求,通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的形式来继承方法,只调用了一次父类构造函数,效率高,也避免了在子类的原型对象上创建不必要的、多余的属性,原型链也不会被改变,核心步骤有:

在"Human"构造函数的原型上添加"getName"函数在”Chinese“构造函数中通过call函数借助”Human“的构造器来获得通用属性Object.create函数返回一个对象,该对象的__proto__属性为对象参数的原型。此时将”Chinese“构造函数的原型和通过Object.create返回的实例对象联系起来最后修复"Chinese"构造函数的原型链,即自身的"constructor"属性需要指向自身在”Chinese“构造函数的原型上添加”getAge“函数
       // 父类
            function Human(name) {
                this.name = name;
                this.kingdom = 'animal'
                this.color = ['yellow', 'white', 'brown', 'black']
            }
            
            Human.prototype.getName = function() {
                return this.name;
            }

            // 子类
            function Chinese(name,age) {
                Human.call(this, name); // 使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类
                this.color = 'yellow';
                this.age = age;
            }
            //寄生:将父类的显示原型的实例对象,作为子类的显示原型
            Chinese.prototype = Object.create(Human.prototype);
            Chinese.prototype.constructor = Chinese;
            Chinese.prototype.getAge = function() {
                return this.age;
            }
JS13 类继承

请补全JavaScript代码,完成类的继承。要求如下:
1. "Chinese"类继承于"Human"类
2. "Human"类实现一个函数"getName",返回该实例的"name"属性
3. "Chinese"类构造函数有两个参数,分别为"name"、"age"
4. "Chinese"类实现一个函数"getAge",返回该实例的"age"属性

知识点:super的传递


    
        
    
    
    	
        
    
JS18 继承 - 原型链继承

请补全JavaScript代码,实现以下功能:
1. 给"Human"构造函数的原型对象添加"getName"方法,返回当前实例"name"属性
2. 将"Chinese"构造函数继承于"Human"构造函数
3. 给"Chinese"构造函数的原型对象添加"getAge"方法,返回当前实例"age"属性

原型链继承核心: 将父类的实例作为子类的原型

      
FED19 发布订阅模式

请补全JavaScript代码,完成"EventEmitter"类实现发布订阅模式。
注意:
1. 同一名称事件可能有多个不同的执行函数
2. 通过"on"函数添加事件
3. 通过"emit"函数触发事件

    class EventEmitter {
                constructor() {
                    this.events = {} // 事件库:以key,value形式,存放所有的事件
                }
                // 订阅事件
                on(event, fn) {
                    // 事件库中没有该事件时,进行事件的注册,如存在,直接放到该事件的,回调函数执行集合中。
                    if(!this.events[event]) {
                        this.events[event] = [fn];
                    } else {
                        this.events[event].push(fn);
                    }
                }
                // 发布事件,相应事件的回调函数要全部执行
                emit(event) {
                    if(this.events[event]) {
                        this.events[event].forEach(fn => fn());
                    }
                }
                
            }
FED20 观察者模式

请补全JavaScript代码,完成"Observer"、"Observerd"类实现观察者模式。要求如下:
1. 被观察者构造函数需要包含"name"属性和"state"属性且"state"初始值为"走路"
2. 被观察者创建"setObserver"函数用于保存观察者们
3. 被观察者创建"setState"函数用于设置该观察者"state"并且通知所有观察者
4. 观察者创建"update"函数用于被观察者进行消息通知,该函数需要打印(console.log)数据,数据格式为:小明正在走路。其中"小明"为被观察者的"name"属性,"走路"为被观察者的"state"属性
注意:
1. "Observer"为观察者,"Observerd"为被观察者

            // 被观察者
            class Observerd {
                constructor(name) {
                    this.name = name;  // name没有初始值,采用传入值
                    this.state = '走路';
                    this.observers = []; // 用于存放观察者
                    
                }
                // 用于保存观察者们:说明实例调用时传入的观察者
                setObserver(observer) {
                    this.observers.push(observer); // 将观察者存起来,好将消息通知到他们
                }
                // 用于设置该观察者"state"并且通知所有观察者
                setState(state) {
                    this.state = state; //将该观察者的状态,进行保留,并同步给其他观察者
                    this.observers.forEach(observer => observer.update(this)); // this指的事被观察者
                }
            }

            // 观察者
            class Observer {
                // 用于被观察者进行消息通知
                update(observerd) {
                    const {name, state} = observerd;
                    console.log(name + '正在' + state);
                }
            }

 使用场景一:一个观察者,对应多个被观察者;

举例:小组成员(被观察者),向组长(观察者)汇报工作状态,组长那会显示每个人不同的状态

 使用场景二:一个被观察者,对应多个观察者;

举例:小组成员(被观察者001)除了向小组长(观察者01)汇报,还要向大组长(观察者02)汇报,会将同一份报告,同步到两个组长那里

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/924888.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)