robbiemie/keep-learning

面试题3(day1)

Opened this issue · 0 comments

手写继承

原型继承

function Parent() {}

Parent.prototype.a = 1;

function Child() {}

Child.prototype = Parent.prototye
Child.prototype.constructor = Child

寄生组合继承

// 超类型构造函数
function SuperType(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function() {
  console.log(this.name);
};

// 辅助函数,实现继承
function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
  prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的 constructor 属性
  subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类型的原型
}

// 子类型构造函数
function SubType(name, age) {
  SuperType.call(this, name); // 第一次调用 SuperType()
  this.age = age;
}

// 寄生组合式继承
inheritPrototype(SubType, SuperType);

// 新的子类型原型方法
SubType.prototype.sayAge = function() {
  console.log(this.age);
};

// 测试寄生组合式继承
var instance = new SubType("Nicholas", 29);
instance.colors.push("black");
console.log(instance.colors); // "red,blue,green,black"
instance.sayName(); // "Nicholas"
instance.sayAge(); // 29

2. instanceof 实现原理

用于检测构造函数的 prototype 属性是否出现在实例对象的原型链上

function instanceOf (ins,cons) {
  if(!ins) return false

  if(ins.__proto__ === cons.prototype) {
    return true
  } else {
    // 原型链继承,子类的原型对象指向父级的原型对象
    ins = ins.__proto__
    return instanceOf(ins, cons)
  }
}

function Child () {}

let c = new Child()

3. promise 限制并发数

const URLS = [
  'A.COM',
  'B.COM',
  'C.COM',
  'D.COM',
  'E.COM',
  'F.COM',
  'G.COM',
]

const resolveUrlFn = url => {
  return new Promise(resolve => {
    setTimeout(()=> {
      resolve(`当前: ${url} 任务,执行完成`)
    }, 1000)
  }).then(res => {
    console.log('异步回调', res)
  })
}

const pool = new PromisePool(3, resolveUrlFn)
pool.start(URLS)

方案1:

class PromisePool {
  constructor(num, callback) {
    this.limit = num;
    this.urls = [];
    this.pools = []
    this.resolveFn = callback
  }

  start(urls) {
    this.urls = urls
    this.exec()
  }

  exec() {
    while(this.urls.length) {
      if(this.pools.length < this.limit) {
        // 加入并发池
        let url = this.urls.pop();
        let task = this.resolveFn(url)
        this.pools.push(task)
        task.then(res => {
          let index = this.pools.findIndex(item => task);
          this.pools.splice(index, 1);
        })
      }
    }
  }
}

方案2:

class PromisePool {
  constructor(num, callback) {
    this.limit = num;
    this.urls = [];
    this.pools = []
    this.resolveFn = callback
  }

  start(urls) {
    this.urls = urls
    while(this.pools.length < this.limit && this.urls.length) {
      this.execTask()
    }
    const race = Promise.race(this.pools);
    this.loop(race)
  }
  loop(race) {
    race.then(() => {
      this.execTask()
      let race = Promise.race(this.pools);
      this.loop(race)
    })
  }
  execTask() {
    let url = this.urls.pop();
    let task = this.resolveFn(url);
    this.pools.push(task);
    task.then(res => {
      let index = this.pools.findIndex(item => item === task)
      this.pools.splice(index, 1);
    })
  }
}

6.https 实现原理

  • 校验证书合法性(获取证书公钥)
  • 用公钥加密,采用的对应加密算法和秘钥
  • 通过对称加密,建立通信

参考文档

7. 节流与防抖

  • 防抖(debounce)

作用是在短时间内多次触发同一个函数,只执行最后一次,或者只在开始时执行

应用场景: 点击事件

/**
 * 创建一个防抖函数
 * @param {Function} func 需要防抖的函数
 * @param {number} wait 等待时间(毫秒)
 * @param {boolean} immediate 是否立即执行
 * @return {Function} 返回防抖处理后的函数
 */
function debounce(func, wait, immediate) {
  let timeout;
  return function() {
    // 保存函数调用时的上下文和参数,传递给 func
    const context = this;
    const args = arguments;

    // 如果定时器已存在,清除之前的定时器
    clearTimeout(timeout);

    // 立即执行,只有在 wait 时间内不再触发事件才再次设定定时器
    if (immediate && !timeout) {
      func.apply(context, args);
    }

    // 设定一个新的定时器,使事件在 wait 毫秒后执行
    timeout = setTimeout(function() {
      timeout = null;
      if (!immediate) {
        func.apply(context, args);
      }
    }, wait);
  };
}
  • 节流(throttle)

节流是指在一段时间内只允许函数执行一次。

应用场景: scroll 事件

/**
 * 创建一个节流函数
 * @param {Function} func 需要节流的函数
 * @param {number} wait 间隔时间(毫秒)
 * @return {Function} 返回节流处理后的函数
 */
function throttle(func, wait) {
  let inThrottle, lastFunc, lastRan;
  return function() {
    const context = this;
    const args = arguments;
    if (!inThrottle) {
      func.apply(context, args);
      lastRan = Date.now();
      inThrottle = true;
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function() {
        if (Date.now() - lastRan >= wait) {
          func.apply(context, args);
          lastRan = Date.now();
        }
      }, Math.max(wait - (Date.now() - lastRan), 0));
    }
  };
}