Skip to content

Latest commit

 

History

History
216 lines (142 loc) · 8.08 KB

问题单2.md

File metadata and controls

216 lines (142 loc) · 8.08 KB
  • 写一个通用的事件侦听器函数

    const EventUtils = {
     // 视能力分别使用dom0||dom2||IE方式 来绑定事件
     // 添加事件
     addEvent: function(element, type, handler) {
      if (element.addEventListener) {
       element.addEventListener(type, handler, false);
      } else if (element.attachEvent) {
       element.attachEvent("on" + type, handler);
      } else {
       element["on" + type] = handler;
      }
     },
    
     // 移除事件
     removeEvent: function(element, type, handler) {
      if (element.removeEventListener) {
       element.removeEventListener(type, handler, false);
      } else if (element.detachEvent) {
       element.detachEvent("on" + type, handler);
      } else {
       element["on" + type] = null;
      }
     },
    
     // 获取事件目标
     getTarget: function(event) {
      return event.target || event.srcElement;
     },
    
     // 获取 event 对象的引用,取到事件的所有信息,确保随时能使用 event
     getEvent: function(event) {
      return event || window.event;
     },
    
     // 阻止事件(主要是事件冒泡,因为 IE 不支持事件捕获)
     stopPropagation: function(event) {
      if (event.stopPropagation) {
       event.stopPropagation();
      } else {
       event.cancelBubble = true;
      }
     },
    
     // 取消事件的默认行为
     preventDefault: function(event) {
      if (event.preventDefault) {
       event.preventDefault();
      } else {
       event.returnValue = false;
      }
     }
    };
  • 函数式编程

    a coding style.

    why functional JavaScript? safer, easier to debug/maintain.

    less codes ,less bugs.

    functions are values. 函数组合,Higher-order functions.

    不用循环,用filter reduce map( 属于Higher-order functions).

    命令时 vs 函数式

    var animals= [
        { name: 'Harold', species: 'dog' }
    ]
    
    /**
    var dogs = []
    for(let i=0; i<animals.length; i++){
    	if(animals[i].species === 'dog'){
    		dogs.push(animals[i])
    	}
    
    }
    */
    
    var dogs = animals.filter(animal => animal.species === 'dog')
  • Curring

What is a curried function? A curried function is a function that takes multiple arguments one at a time. Given a function with 3 parameters, the curried version will take one argument and return a function that takes the next argument, which returns a function that takes the third argument.

函数不是一次获取有得参数,而是拿到第一个参数,并返回一个接收第二个参数的函数,这个函数在返回新的接收第三个参数的函数。以此类推,直到所有的参数都获取到了,才会返回结果。

why

let dragons = [
    { name: 'karo', element: 'lightning' },
    { name: 'dommer', element: 'fire' },
]
// non-curring
let hasElement = (element, obj) => obj.element === element
let lightningDragons = dragons.filter(x => hasElement('lightning', x))

// curring
import _ from 'lodash'
let hasElement = _.curry((element, obj) => obj.element === element)
let lightningDragons = dragons.filter(hasElement('lightning'))

柯里化有3个常见作用:1. 参数复用;**2. 提前返回;**3. 延迟计算/运行

  • 什么是高阶函数?

    高阶函数就是将函数作为参数或返回值的函数。

  • 手动实现 Array.prototype.map 方法

  • 手动实现Array.prototype.filter方法

  • 手动实现Array.prototype.reduce方法

  • js 的深浅拷贝

  • 手写 call、apply 及 bind 函数

  • 函数柯里化的实现

  • js 模拟 new 操作符的实现

  • 什么是回调函数?回调函数有什么缺点

    回调函数是一个函数作为参数传进另一个函数中,在合适的时机再调用。

    回调地狱。代码不利于阅读和维护,难以复用。

  • Promise 是什么,可以手写实现一下吗?

    Promise 对象是一个代理对象(代理一个值),被代理的值在 Promise 对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的 promise 对象。

    一个 Promise 有以下几种状态:

    • pending: 初始状态,既不是成功,也不是失败状态。
    • fulfilled: 意味着操作成功完成。
    • rejected: 意味着操作失败。

    这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了,也就是说一旦状态变为 fulfilled/rejected 后,就不能再次改变。

    上一条我们说过 Promise 可以解决回调地狱的问题,没错,pending 状态的 Promise 对象会触发 fulfilled/rejected 状态,一旦状态改变,Promise 对象的 then 方法就会被调用;否则就会触发 catch。

    其实 Promise 也是存在一些缺点的,比如无法取消 Promise,错误需要通过回调函数捕获。

  • Iterator是什么,有什么作用?试给一个对象实现for of?

    Iterator 的作用有三个:

    1. 为各种数据结构,提供一个统一的、简便的访问接口;
    2. 使得数据结构的成员能够按某种次序排列;
    3. ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费。
  • Generator函数是什么,有什么作用?

  • 什么是 async/await 及其如何工作,有什么优缺点?

    优缺点:

    async/await的优势在于处理 then 的调用链,能够更清晰准确的写出代码,并且也能优雅地解决回调地狱问题。当然也存在一些缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低。

  • instanceof 的原理是什么,如何实现

  • js 的节流与防抖

  • 什么是设计模式?

    设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

  • 9 种前端常见的设计模式

  • 外观模式(Facade Pattern)

    外观模式是最常见的设计模式之一,它为子系统中的一组接口提供一个统一的高层接口,使子系统更容易使用。简而言之外观设计模式就是把多个子系统中复杂逻辑进行抽象,从而提供一个更统一、更简洁、更易用的 API。很多我们常用的框架和库基本都遵循了外观设计模式,比如 JQuery 就把复杂的原生 DOM 操作进行了抽象和封装,并消除了浏览器之间的兼容问题,从而提供了一个更高级更易用的版本。其实在平时工作中我们也会经常用到外观模式进行开发,只是我们不自知而已。

    1. 兼容浏览器事件绑定
    2. 封装接口
  • 代理模式(Proxy Pattern)

    是为一个对象提供一个代用品或占位符,以便控制对它的访问

    假设当 A 在心情好的时候收到花,小明表白成功的几率有 60%,而当 A 在心情差的时候收到花,小明表白的成功率无限趋近于 0。小明跟 A 刚刚认识两天,还无法辨别 A 什么时候心情好。如果不合时宜地把花送给 A,花 被直接扔掉的可能性很大,这束花可是小明吃了 7 天泡面换来的。但是 A 的朋友 B 却很了解 A,所以小明只管把花交给 B,B 会监听 A 的心情变化,然后选 择 A 心情好的时候把花转交给 A,代码如下:

    • HTML 元 素事件代理
    • ES6 的 proxy
  • 工厂模式(Factory Pattern)

  • 单例模式(Singleton Pattern)

  • 策略模式(Strategy Pattern)

  • 策略模式简单描述就是:对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。把它们一个个封装起来,并且使它们可以互相替换

  • 迭代器模式(Iterator Pattern)

  • 观察者模式(Observer Pattern)

  • 中介者模式(Mediator Pattern)

  • 中介者模式(Mediator Pattern)