JS

2020/06/09 js

1、如何在ES5 下面实现let

(function(){
  for(var i = 0; i < 5; i ++){
    console.log(i)  // 0 1 2 3 4
  }
})();

console.log(i)      // Uncaught ReferenceError: i is not defined

babel 转

for(let i=0;i<10;i++>){
  console.log(i)
}
console.log(i)
// 转成如下
for(var _i=0;_i<10;_i++>){
  console.log(_i)
}
console.log(i) // Uncaught ReferenceError: i is not defined

2、如何在ES5环境下实现const

// Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
function _const(key, value) {    
    const desc = {        
        value,        
        writable: false    
    }    
    Object.defineProperty(window, key, desc)
}
    
_const('obj', {a: 1})   //定义obj
obj.b = 2               //可以正常给obj的属性赋值  
obj = {}                //无法赋值新对象

3、手写bind

if(Function.prototype._bind === undefined){
  Function.prototype._bind = function (ctx){
    let args = [].slice.call(arguments,1)
    let that = this
    return function (){
      that.apply(ctx,args.concat([].slice(arguments,1)))
    }
  }
}

4、手写call

  Function.prototype.call = function call(ctx,...args){
    ctx = ctx || window
    ctx.fn = this
    let result = ctx.fn(...args)
    delete ctx.fn
    return result
  }

5、手写apply

  Function.prototype.apply = function call(ctx,args){
    ctx = ctx || window
    ctx.fn = this
    let result = ctx.fn(...args)
    delete ctx.fn
    return result
  }

6、手写new

  function new (){
    let obj = {}
    let Constructor= [].shift.call(arguments)
    obj.__proto__ = Constructor.prototype
    let result = Constructor.apply(obj,arguments)
    return result instanof Object?result:obj
  }

7、手写map

function map(arr, mapCallback) {
  // 首先,检查传递的参数是否正确。
  if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') { 
    return [];
  } else {
    let result = [];
    // 每次调用此函数时,我们都会创建一个 result 数组
    // 因为我们不想改变原始数组。
    for (let i = 0, len = arr.length; i < len; i++) {
      result.push(mapCallback(arr[i], i, arr)); 
      // 将 mapCallback 返回的结果 push 到 result 数组中
    }
    return result;
  }
}

8、手写filter

function filter(arr, filterCallback) {
  // 首先,检查传递的参数是否正确。
  if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') 
  {
    return [];
  } else {
    let result = [];
     // 每次调用此函数时,我们都会创建一个 result 数组
     // 因为我们不想改变原始数组。
    for (let i = 0, len = arr.length; i < len; i++) {
      // 检查 filterCallback 的返回值是否是真值
      if (filterCallback(arr[i], i, arr)) { 
      // 如果条件为真,则将数组元素 push 到 result 中
        result.push(arr[i]);
      }
    }
    return result; // return the result array
  }
}

9、手写reduce

  function reduce(arr, reduceCallback, initialValue) {
  // 首先,检查传递的参数是否正确。
  if (!Array.isArray(arr) || !arr.length || typeof reduceCallback !== 'function') 
  {
    return [];
  } else {
    // 如果没有将initialValue传递给该函数,我们将使用第一个数组项作为initialValue
    let hasInitialValue = initialValue !== undefined;
    let value = hasInitialValue ? initialValue : arr[0]

    // 如果有传递 initialValue,则索引从 1 开始,否则从 0 开始
    for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) {
      value = reduceCallback(value, arr[i], i, arr); 
    }
    return value;
}}

10、手写intanceof

// instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
// left:obj  right:Function

function myInstanceof(left, right) {
  let prototype = right.prototype
  left = left.__proto__
  while (true) {
    if (left === null || left === undefined)
      return false
    if (prototype === left)
      return true
    left = left.__proto__
  }
}

11、防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

function debounce(fn) {
  let timer = null;
  return function () {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments)
    }, 500)
  }
}
function sayHi() {
  console.log("防抖成功")
}
var inp = document.getElementById('inp')
inp.addEventListener('input', debounce(sayHi))

12、节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

function throttle(fn) {
  let canRun = true;
  return function () {
    if (!canRun) return
    canRun = false
    fn.apply(this, arguments)
    setTimeout(() => {
      canRun = true
    }, 500)
  }
}
function sayHi(e) {
  console.log(e.target.innerHeight, e.target.innerWidth)
}
window.addEventListener('resize', throttle(sayHi))

13、简单深拷贝deepClone

function deepClone (source){
    if(!source && typeof source !== 'object'){
        throw new error("please insert object")
    }
    let target = source.constructor === Array ? []:{}
    Object.keys(source).forEach(keys =>{
        if(source[keys] && typeof source[keys] === 'object'){
            target[keys] = deepClone(source[keys])
        }else{
            target[keys] = source[keys]
        }
    })
    return target
}
console.log(deepClone([,3,4]))
}

14、手写promise

class myPromise {
  constructor(executor){
    this._resloveQueue =[]
    this._rejectQueue = []
    let _reslove = (val)=>{
      while (this._resloveQueue.length) {
        const callback = this._resloveQueue.shift()
        callback(val)
      }
    }
    let _reject = (val)=>{
      while (this._rejectQueue.length > 0) {
        const callback =this._rejectQueue.shift()
        callback(val)
        }
      }
    executor(_reslove,_reject)
  }
  
  then(resloveFn,rejectFn){
    this._resloveQueue.push(resloveFn)
    this._rejectQueue.push(rejectFn)
  }
}

const p1 = new myPromise((reslove,reject)=>{
  setTimeout(() => {
    reslove("reslut")
  }, 1000);
})

p1.then(res => console.log(res))

Search

    Table of Contents