前端面试每日3+2(第26天)

12/27/2019

当你发现自己的才华撑不起你的野心时,就请安静下来学习吧!

鲁迅说过:答案仅供参考...

# 1、node中的EventEmitter是什么?如果捕获EventEmitter的错误?

解析:

什么是EventEmitter?

  • EventEmitter是node中实现观察者模式的类,主要功能是监听和发射消息,用于处理很多模块的交互问题。
  • 大多数Node的Api惯用异步事件驱动架构,其中某些类型的对象(触发器 Emitter)会触发命名事件来调用函数(监听器 Listener)
  • 所有触发事件的对象都是EventEmitter类的实例。
  • 当EventEmitter对象触发一个事件时,所有绑定在该事件上的函数都会被同步的调用。
  • 例如:net.Server每次新连接时触发事件,fs.ReadStream会再打开文件时触发事件,stream会再数据可读时触发事件。
  • 栗子:
    const EventEmitter = require('events');
    class MyEmitter extends EventEmitter {}
    const myEmitter = new MyEmitter();
    // 注册监听器
    myEmitter.on('event', () => {
    console.log('触发事件');
    });
    // 监听错误。内部封装事件
    myEmitter.on('error', (err) => {
    console.error('错误信息');
    });
    // 触发事件
    myEmitter.emit('event');
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

简单实现一个自己的EventEmitter:

  • MyEnvent.js

    /**
     * 实现的方法:
     * on
     * once
     * off
     * emit
     */
    
    // node源码 多数都是构造函数
    function EventEmitter() {
        this._events = Object.create(null);
    }
    
    // 订阅 创建关系
    EventEmitter.prototype.on = function (eventName, callback) { // {'sayHi':[]}
        if (!this._events) { // 没有的话 创建一个对象
            // this._events = {}
            this._events = Object.create(null);
        }
        if (eventName !== 'newListener') {
            if (this._events['newListener']) {
                this._events['newListener'].forEach(fn => fn(eventName))
            }
        }
        let arr = this._events[eventName] || (this._events[eventName] = []);
        arr.push(callback)
    
    } 
    
    EventEmitter.prototype.once = function (eventName, callback) {
        const once = (...args) => { // 高阶函数
            callback(...args); // 先执行原有的逻辑
            this.off(eventName, once); // 在将这个函数移除掉
        }
        once.l = callback
        this.on(eventName, once); // {'sayHi':[fn1.fn2]}
    }
    
    // 让对应的函数依次执行
    EventEmitter.prototype.emit = function (eventName, ...args) {
        if (!this._events) {
            this._events = Object.create(null);
        }
        if (this._events[eventName]) {
            this._events[eventName].forEach(fn => fn(...args));
        }
    }
    
    EventEmitter.prototype.off = function (eventName, fn) {
        if (this._events[eventName]) {
            //  this._events[eventName] = [once]
            this._events[eventName] = this._events[eventName].filter(item => {
                return item !== fn && item.l !== fn
            })
        }
    }
    
    // 导出
    module.exports = EventEmitter;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
  • el.js

    // 引入自己写的MyEnvent.js
    const EventEmitter =require('./MyEnvent');
    const ev = new EventEmitter()
    
    ev.on('newListener', (eventName)=>{
        console.log('newListener',eventName)
    })
    ev.on('sayHi', (data) => {
        console.log('hi!My name is >>', data)
    })
    ev.on('sayHi', (data) => {
        console.log('你好,我的名字叫 >>', data)
    })
    ev.on('sayAge', (data) => {
        console.log('hi!My age is >>', data)
    })
    ev.on('sayAge', (data) => {
        console.log('你好!我的年龄是>>', data,'岁')
    })
    const fvPass = (data) => {
        console.log('hi!My pass is >>', data)
    }
    ev.on('pass', fvPass)
    
    ev.emit('sayHi', 'wby')
    ev.emit('sayAge', '20')
    ev.emit('pass', '123456')
    ev.off('pass', fvPass)
    ev.emit('pass', '333333')
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

# 2、less和sass是什么?有什么区别。为什么要实用less和sass?

解析:

是什么?

  • less (opens new window)sass (opens new window)都是动态样式语言,是css预编译器。CSS预处理器用一种专门的编程语言,进行Web页面样式的设计,然后再编译成正常的CSS文件,以供项目使用。CSS预处理器为CSS增加一些编程的特性,无需考虑浏览器的兼容性问题。
  • Less是一种动态样式语言. 对CSS赋予了动态语言的特性,如变量、继承、运算、函数。Less 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可在服务端运行。
  • Sass是一种动态样式语言,Sass语法属于缩排语法,比css比多出好些功能(如变量、嵌套、运算,混入(Mixin)、继承、颜色处理,函数等),更容易阅读。

Sass与Scss是什么关系?

  • Sass的缩排语法,对于写惯css前端的web开发者来说很不直观,也不能将css代码加入到Sass里面,因此sass语法进行了改良,Sass 3就变成了Scss(sassy css)。与原来的语法兼容,只是用{}取代了原来的缩进。

less和sass的区别:

  • 编译环境不同
    • less:Less是基于JavaScript,是在客户端处理的。
    • sass:Sass是基于Ruby的,是在服务器端处理的。
  • 变量符合不同:sass$,less@
  • 输出设置:sass支持输出设置,less不支持
  • sass支持条件语句,less不支持

# 2、什么是原生app?优缺点。

解析:

什么是?

  • 原生app是利用Android、IOS平台官方的开发语言、开发类库、开发工具进行开发。比如Android用的java,IOS用的Object-c语言。在应用性能和交互体验上是很好的。

优点:

  • 可以访问手机的所有功能、可实现功能齐全
  • 运行速度快、性能好,用户体验好
  • 支持大量图形动画,反应快
  • 快捷使用设备提供的接口

缺点:

  • 开发成本高、周期长、Android和IOS需要单独开发

# 4、什么是混合app(Hybrid App)?

解析:

是什么?

  • 利用了原生app的开发技术和html5开发技术,是原生和html5技术的混合使用。混合比例不限

优点

  • 比web版实现的功能更多,h5可以通过原生app提供的方法调用设备的功能。
  • 兼容平台多
  • 可离线运行

缺点

  • 用户体验不如原生本地应用
  • 性能稍慢
  • 技术不够成熟

# 5、什么是webApp。

解析:

是什么

  • 本质就是浏览器功能的叠加,用普通的web开发语言html、js、css开发,通过浏览器运行。 优点:
  • 开发成本低、周期端
  • 可以在不同平台运行,支持返回广

缺点、

  • 对网络要求高,离线无法做任何操作
  • 功能有限,无法直接方便的调用设备提供的方法
  • 运行速度满,页面不能承载很多内容
  • 图片和动画支持性不高
  • 浏览器兼容问题
Last Updated: 12/29/2019, 10:23:28 AM
    asphyxia
    逆时针向