记录手写JS

Posted 三水草肃

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记录手写JS相关的知识,希望对你有一定的参考价值。

手写JS:

有了这些手写JS,从此不在怕面试手撕JS
不定时更新


手写Call

Function.prototype.myCall = function (context) {
    if (typeof this !== 'function') {
        throw new TypeError('error')
    }
    context = context || window
    context.fn = this
    const args = [...arguments].slice(1)
    const result = context.fn(...args)
    delete context.fn
    return result
}

/* apply */

Function.prototype.myApply = function (context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    context.fn = this
    let result
    if (arguments[1]) { // 取得除了fn之外的数据
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete result.fn
    return result
}

/* bind */

Function.prototype.myBind = function (context) {
    if (typeof this !== 'function') {
        throw new TypeError('error')
    }
    const that = this
    const args = [...arguments].slice(1)
    return function F() {
        if (this instanceof F) {
            return new that(...args, ...arguments)
        }
        return that.apply(context, args.concat(...arguments))
    }
}

深拷贝

function deepClone(obj) {
  let objClone = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj === "object") {
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (obj[key] && typeof obj[key] == "object") {
          objClone[key] = deepClone(obj[key]);
        } else {
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

手写instance

function instanceOf_my(left, right) {
    const rightPrototype = right.prototype
    let leftInst = Object.getPrototypeOf(left)
    while(true) {
        if(leftInst === null) {
            return false
        }
        if(leftInst === rightPrototype) {
            return true
        }
        leftInst = Object.getPrototypeOf(leftInst)
    }
}

扩展instanceof,判断 let num = 1

class MyNumber {
    static [Symbol.hasInstace](instance) {
        return typeof instace === 'number'
    }
}

console.log(num instanceof MyNumber)

数组扁平化

function flatten(arr) {
    return arr.reduce((prev, curr) => {
        return prev.concat(Array.isArray(curr) ? flatten(curr) : curr)
    }, [])
}

合并多个数组

function fn() {
    return arr = [].concat.apply([],arguments)
}
把类数组转化为数组,类数组是原型中有length属性
[].shift.call(arguments)

实现new

function My_new () {
    let res  = {}
    let con = [].shift.call(arguments)
    res.__proto__ = con.prototype
    let conRes = con.apply(res,arguments)
    return conRes instanceof Object ? conRes : res
}

// 节流

function throttle(fn, time) {
  let last = 0;
  return function () {
    let context = this;
    let args = arguments;
    let now = +new Date();
    if (now - last >= time) {
      last = now;
      fn.apply(context, args);
    }
  };
}

// 防抖

function debounce(fn, time) {
  let timer = null;
  return function () {
    let context = this;
    let args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(context, args);
      timer = null;
    }, time);
  };
}

书写map

Array.function.Map = function (cb, context) {
    let newArr = []
    for (let i = 0; i < this.length; i++) {
        if (cb && typeof cb === 'function') {
            let val = cb.call(context, this[i], i, this)
            newArr.push(val)
        }
    }
    return newArr
}

数组乱序

let arr = [9,8,7,5,6,5,4,5,2,2,2]
arr.sort(() => {
    return Math.random() - 0.5
})

冒泡排序

/* 两两比较 */
function bubleSort(arr) {
    var len = arr.length
    for (let outer = len; outer >= 2; outer--) {
        for (let inner = 0; inner <= outer - 1; inner++) {
            if (arr[inner] > arr[inner + 1]) {
                [arr[inner], arr[inner + 1]] = [arr[inner + 1], arr[inner]]
            }
        }
    }
    return arr
}
console.log(bubleSort([1, 2, 5, 44, 56, 5, 85, 5]));


function fn(arr) {
    for(let i = 0 ; i < arr.length -1; i++) {
        for(let j = i+1;j <arr.length;j++){
            if(arr[i] > arr[j]) {
                [arr[i], arr[j]] = [arr[j], arr[i]]
            }
        }
    }
    return arr
}

/* 选择排序: 遍历自身以后的元素,最小的元素跟自己调换位置 */
function selectSort(arr) {
    var len = arr.length
    for (let i = 0; i < len - 1; i++) {
        for (let j = 1; j < len; j++) {
            if (arr[i] > arr[j]) {
                [arr[i], arr[j]] = [arr[j], arr[i]];
            }
        }
    }
    return arr
}

/* 插入排序:即将元素插入到已排序好的数组中 */
function insertSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        for (let j = i; j > 0; j++) {
            if (arr[j] < arr[j - 1]) {
                [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
            } else {
                break;
            }
        }
    }
    return arr;
}

Number 扩展

 Function.prototype.method = function (name, func) {
       this.prototype[name] = func
    // Number.intergegege = function () { return Math[this < 0 ? 'ceil' : 'floor'](this) }
    return this
}
Number.method('intergegege', function () {
     return Math[this < 0 ? 'ceil' : 'floor'](this)
})
console.log(Boolean instanceof Function) // true

随机数

function getRandom(start, end) {
    return Math.floor(Math.random() * (end - start + 1) + start)
}

洗牌算法

function shuas(arr) {
    for (let i = 0; i < arr.length; i++) {
        const j = Math.floor(Math.random() * (i + 1));
        [arr[i], arr[j]] = [arr[j], arr[i]]
    }
    return arr
}
console.log(shuas([1,5,6,8,6,5,6,2,21,4,54]));

手写Object.is()

function ObjectIs(x, y) {
  if (x === y) {
    return x !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}
console.log(NaN == NaN) false
console.log(+0 == -0)true
console.log(ObjectIs(+0 , -0))false
console.log(ObjectIs(+NaN , -NaN)) true

寄生组合继承

function Parent5 () { 
this.name = 'parent5';
 this.play = [1, 2, 3]; 
}
 function Child5() { 
Parent5.call(this); 
this.type = 'child5'; 
} 
Child5.prototype = Object.create(Parent5.prototype); 
Child5.prototype.constructor = Child5;

数组扁平化

function flatten(arr) {
    return arr.reduce((prev, curr) => {
        return prev.concat(Array.isArray(curr) ? flatten(curr) : curr)
    }, [])
}
while(arr.some(Array.isArray)) {
    arr = [].concat(...arr)
}

Map手写

Array.prototype.map = function(callbackFn, thisArg) {
    // 处理数组类型异常
    if (this === null || this === undefined) {
      throw new TypeError("Cannot read property 'map' of null or undefined");
    }
    // 处理回调类型异常
    if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
      throw new TypeError(callbackfn + ' is not a function')
    }
    // 草案中提到要先转换为对象
    let O = Object(this);
    let T = thisArg;
  
    
    let len = O.length >>> 0;
    let A = new Array(len);
    for(let k = 0; k < len; k++) {
      // 还记得原型链那一节提到的 in 吗?in 表示在原型链查找
      // 如果用 hasOwnProperty 是有问题的,它只能找私有属性
      if (k in O) {
        let kValue = O[k];
        // 依次传入this, 当前项,当前索引,整个数组
        let mappedValue = callbackfn.call(T, KValue, k, O);
        A[k] = mappedValue;
      }
    }
    return A;
  }
 length >>> 0, 字面意思是指"右移 0 位",但实际上是把前面的空位用0填充,这里的作用是保证len为数字且为整数

reduce手写

Array.prototype.reduce = function(callbackfn, initialValue) { 
// 异常处理,和 map 一样 // 处理数组类型异常 
if (this === null || this === undefined) {
 throw new TypeError("Cannot read property 'reduce' of null or undefined");
 } 
// 处理回调类型异常 
if (Object.prototype.toString.call(callbackfn) != "[object Function]") {
 throw new TypeError(callbackfn + ' is not a function') 
} 
let O = Object(this); 
let len = O.length >>> 0;
 let k = 0; 
let accumulator = initialValue;
 if (accumulator 以上是关于记录手写JS的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题之手写promise

JS异步编程2:手写Promise

js面试题之手写节流函数和防抖函数

手写js代码格式化json数据

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

CSP核心代码片段记录