javascript手撕前端面试题:寄生组合式继承|发布订阅模式|观察者模式(代码片段)

海底烧烤店ai 海底烧烤店ai     2022-12-15     138

关键词:

🧑‍💼个人简介:大三学生,一个不甘平庸的平凡人🍬
🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)
👉 你的一键三连是我更新的最大动力❤️!


文章目录

1、寄生组合式继承

要求

补全JavaScript代码,要求通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。要求如下:

  1. 给"Human"构造函数的原型上添加"getName"函数,该函数返回调用该函数对象的"name"属性
  2. 给"Chinese"构造函数的原型上添加"getAge"函数,该函数返回调用该函数对象的"age"属性

思路

寄生组合式继承是引用类型最理想的继承范式,它融合了组合式继承寄生式继承的优点,而组合式继承又是融合了原型链借用构造函数的技术,从而发挥两者之长,所以寄生组合式继承实际是三种技术的融合。

  • 寄生式继承的思路是:创建一个仅用于封装继承过程的函数
  • 组合式继承的思路是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

这一题的思路是:

  1. 先创建一个inheritPrototype函数,该函数属于寄生式继承模式,作用是实现实现对原型属性和方法的继承:

    // subType子类构造函数,superType父类构造函数
    function inheritPrototype(subType,superType)
    	 // Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。
         var prototype = Object.create(superType.prototype); // 创建父类型的一个副本对象
         prototype.constructor = subType; // 修复prototype的constructor 
         subType.prototype = prototype; // 将prototype设为subType的原型
     
    

    这里涉及到原型链的知识:一个构造函数的prototype指向它的原型对象,而它的原型对象的constructor属性又指向到这个构造函数。上面的代码中因为要让prototype设置为subType的原型,所以prototype.constructor需要指向到subType

    调用inheritPrototype后,subType就继承了superType的属性和方法,这些属性和方法存在于subType的原型上,这样一来subType的所有实例就能访问到同一个存在的属性或方法(这些属性和方法相当于是公有的)。

  2. 给"Human"构造函数的原型上添加"getName"函数:

    Human.prototype.getName=function ()
       return this.name;
    
    
  3. 通过借用构造函数来实现ChineseHuman实例属性的继承:

    function Chinese(name,age) 
    	// 继承了Human,还传了参数
        Human.call(this,name); // 借用构造函数模式
        this.age = age;
        this.color = 'yellow';
    
    

    Chinese内部调用Human构造函数,实际上是为Chinese的实例设置了Human上具有的属性和方法(不包含Human原型上的属性和方法),这样一来Chinese的所有实例就能拥有自己的属性和方法(这些属性和方法相当于是私有的)。

  4. 调用inheritPrototype(Chinese,Human); 来实现ChineseHuman原型属性和方法的继承。

  5. 给"Chinese"构造函数的原型上添加"getAge"函数:

    Chinese.prototype.getAge=function()
        return this.age;
    
    

代码

function inheritPrototype(subType,superType) 
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;



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.age = age;
    this.color = 'yellow';


inheritPrototype(Chinese,Human);


Chinese.prototype.getAge = function() 
    return this.age;

这题寄生组合式继承涉及到了JavaScript面向对象的程序设计,需要理解对象,构造函数,原型,原型链等的知识,博主之后会出文章对JavaScript面向对象的程序设计进行讲解,敬请期待!

2、发布订阅模式

要求

补全JavaScript代码,完成"EventEmitter"类实现发布订阅模式。

注意:

  1. 同一名称事件可能有多个不同的执行函数
  2. 通过"on"函数添加事件
  3. 通过"emit"函数触发事件

思路

  • 因为同一名称事件可能有多个不同的执行函数,所以我们需要先定义一个handler对象用来保存订阅事件的列表,对象内的key为订阅事件名称,value是一个包含该订阅事件所有的执行函数的数组
  • on函数接收两个参数,分别代表订阅事件名称和执行函数,在on函数内判断handler对象内是否存在该订阅事件,从而决定是向handler对象内初始化该订阅事件还是向该订阅事件的函数列表中添加新函数。
  • emit函数接收多个参数,第一个参数代表订阅事件名称,后面的参数是需要向订阅事件处理函数传递的参数,handler对象内存在该订阅事件时就遍历执行该订阅事件的函数列表数组中的所有处理函数。

代码

class EventEmitter 
    // 补全代码
    constructor() 
        this.handler = ; // 保存订阅事件的列表
    
    on(type, fn) 
        const fnArr = this.handler[type];
        if (fnArr) 
            // 如果订阅事件存在,存放订阅事件的回调函数
            fnArr.push(fn);
         else 
            // 如果订阅事件不存在,则初始化该事件
            // 因为同一名称事件可能有多个不同的执行函数,所以用数组来存放所有的执行函数
            this.handler[type] = [fn];
        
    

    emit(type, ...args) 
        const fnArr = this.handler[type];
        if (fnArr) 
            // 如果订阅事件存在,遍历并执行订阅事件的处理函数
            fnArr.forEach(cb => cb(...args))
        

    

测试:

let sign1 = 0;
let sign2 = 0;
const emitter = new EventEmitter();
emitter.on('add', function ()  sign1++ );
emitter.emit('add');
emitter.on('add', function ()  sign2++ );
emitter.emit('add');
const judge = sign1 === 2 && sign2 === 1;
console.log(judge); // true

3、观察者模式

要求

补全JavaScript代码,完成"Observer"、"Observerd"类实现观察者模式

要求如下:

  1. 被观察者构造函数需要包含"name"属性和"state"属性且"state"初始值为"走路"。
  2. 被观察者创建"setObserver"函数用于保存观察者们。
  3. 被观察者创建"setState"函数用于设置该观察者"state"并且通知所有观察者。
  4. 观察者创建"update"函数用于被观察者进行消息通知,该函数需要打印(console.log)数据,数据格式为:小明正在走路。其中"小明"为被观察者的"name"属性,"走路"为被观察者的"state"属性。

注意:

  1. "Observer"为观察者,"Observerd"为被观察者。

思路

  • 根据题目的第二个要求:被观察者创建"setObserver"函数用于保存观察者们。可得知setObserver函数应该接受一个observer参数,该参数代表观察者,同时因为要保存这些观察则,所以在Observerd被观察者初始化的时候应该创建一个用来保存观察者的数组observers
  • 根据题目的第三个要求和第四个要求可知setState函数接受一个state参数用来更新Observerd被观察者自身的state,同时setState函数还应该遍历observers数组,并调用数组中的每一项的update方法,以此来通知所有观察者。

代码

// 被观察者
class Observerd 
    constructor(name) 
        this.name = name
        this.state = '走路'
        this.observers = [] // 存放观察者
    
    setObserver(observer) 
        this.observers.push(observer)
    
    setState(state) 
        this.state = state
        // 遍历通知每一个观察者
        this.observers.forEach(observer => 
            observer.update(this)
        )
    

// 观察者
class Observer 
	// update被被观察者(Observerd)调用,用来接收被观察者的数据
    update(observerd) 
        console.log(observerd.name + '正在' + observerd.state);
    

手撕前端面试题javascript~总成绩排名子字符串频次统计继承判断斐波那契数组等(代码片段)

前端JavaScript面试题🍓🍓总成绩排名🍓🍓子字符串频次🍓🍓继承🍓🍓判断斐波那契数组🍓🍓js中哪些操作会造成内存泄漏?html页面的骨架,相当于人的骨头,只有骨头是不是看着... 查看详情

#yyds干货盘点#前端歌谣的刷题之路-第一百五十七题-寄生组合式继承

...酷本题目源自于牛客网微信公众号前端小歌谣题目请补全JavaScript代码,要求实现对象参数的深拷贝并返回拷贝之后的新对象。注意:1.参数对象和参数对象的每个数据项的数据类型范围仅在数 查看详情

面试前端面试常考手写题-javascript-css(代码片段)

持续更新中…文章目录1.CSS布局1.1盒子居中对齐1.2两栏布局1.3三栏布局双飞翼圣杯1.4品字布局2.JS手写函数2.1手写原生PromisePromise.allPromise.racePromise.resolve()Promise.reject()callapplybindnewinstanceof2.2自定义函数数组去重数组扁平化深拷贝深... 查看详情

面向面试编程——javascript继承的6种方法

javascript继承的6种方法1,原型链继承2,借用构造函数继承3,组合继承(原型+借用构造)4,原型式继承5,寄生式继承6,寄生组合式继承1.原型链继承.<scripttype="text/javascript">functionPerson(name,sex){this.name=name;this.sex=sex;this.friends=[‘... 查看详情

手撕前端面试题javascript(代码片段)

🍖🍖作者:不良使🍖🍖🍖🍖潜力创作新星华为云享专家博主🍖🍖🍖🍖🍖Python+Android🍖🍖🍖🍖🍖🍖博客 查看详情

手撕前端面试题javascript(代码片段)

前端的那些基本标签🍓🍓浅拷贝🍓🍓简易深拷贝🍓🍓深拷贝🍓🍓什么是深拷贝,什么是浅拷贝,二者有什么区别,平时改怎么区分呢?💖💖js中不同类型存放的位置不... 查看详情

javascript-------寄生组合式继承

组合继承在前面有说过,也是JavaScript中最常用的一个继承模式;不过,它也有自己的不足。组合继承最大的问题就是无论什么情况,都会调用两次构造函数:那我们来回顾下组合式继承基本模式:1functionSuperType(name){2this.name=name;... 查看详情

javascript组合继承原型链继承寄生继承

Javascript继承通常有三种方式。第一种:组合式继承:functionSuperType(name){this.name=name;this.colors=["red","blue","green"];}SuperType.prototype.sayName=function(){console.log(this.name);};functionSubType(name,age){//通过c 查看详情

[javascript高手之路]寄生组合式继承的优势

在之前javascript面向对象系列的文章里面,我们已经探讨了组合继承和寄生继承,回顾下组合继承:function Person( uName ){            this.skills = [ ‘php‘,& 查看详情

[js高手之路]寄生组合式继承的优势

在之前javascript面向对象系列的文章里面,我们已经探讨了组合继承和寄生继承,回顾下组合继承:1functionPerson(uName){2this.skills=[‘php‘,‘javascript‘];3this.userName=uName;4}5Person.prototype.showUserName=function(){6returnthis.userName;7}8func 查看详情

javascript继承笔记

//原型(prototype):原型是一个对象,其他对象可以通过它实现属性继承 /*笔记: *1.类式继承:通过原型链继承的方式 *2.原型式继承:对类式继承的封装 *3.寄生式继承:对原型继承的二次封装,并且在第二次封装过程中对继... 查看详情

javascript继承的实现

JavaScript通过函数的方式实现继承,其中分为原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承与寄生组合式继承。其中最后性能最好的是寄生组合式继承。具体分析如下原型链继承实现形... 查看详情

javascript手撕前端面试题:手写object.create|手写function.call|手写function.bind(代码片段)

🖥️NodeJS专栏:Node.js从入门到精通🖥️博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)🖥️TypeScript知识总结:TypeScript从入门到精通(... 查看详情

javascript手撕前端面试题:事件委托|判断url是否合法|全排列(代码片段)

🖥️NodeJS专栏:Node.js从入门到精通🖥️博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)🖥️TypeScript知识总结:TypeScript从入门到精通(... 查看详情

寄生组合式继承

//组合继承是javascript中最常用的继承模式,不过,他也有自己的不足,组合继承最大的问题是无论什么情况下,//都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数的内部。//没错,子... 查看详情

javascript面向对象(代码片段)

JavaScript面向对象(四)原型赋值继承寄生组合式继承原型式继承寄生式继承寄生组合式继承的实现简便方法原型判断方法补充hasOwnPropertyin操作符instanceofisPrototypeOf原型赋值继承在上篇文章中,借用构造函数方法实现... 查看详情

前端面试题----手撕javascriptcallapplybind函数(超详细)(代码片段)

手撕JavaScriptcallapplybind函数文章目录手撕JavaScriptcallapplybind函数一、callapplybind函数的基本用法二、手写myCall方法ES6实现myCall方法ES5实现myCall方法三、手写myApply方法四、手写myBind方法一、callapplybind函数的基本用法  首先这三个... 查看详情

javascript手撕前端面试题:手写new操作符|手写object.freeze(代码片段)

🖥️NodeJS专栏:Node.js从入门到精通🖥️博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)🖥️TypeScript知识总结:TypeScript从入门到精通(... 查看详情