天天看点

前端为什么有的接口明明是成功回调却执行了.catch失败回调_想知道前端面试如何手写模拟实现吗?...模拟call、apply、bind实现快速、希尔、归并排序数组去重Proxy使用get拦截,实现数组读取负数的索引Promise的实现

let obj = {    name: 'Michael',    age: 18,    others: {        hobbies: ['basketball', 'gambling'],        team: 'Bulls',    },}// 递归拷贝function deepClone(obj) {    if (obj instanceof RegExp) return new RegExp(obj);    if (obj instanceof Date) return new Date(obj);    if (obj === null || typeof obj !== 'object') return obj //如果不是引用类型则直接返回    let newObj = new obj.constructor();    //如果obj是数组,newObj=[];如果obj是对象,newObj={}    for (let key in obj) {        if (obj.hasOwnProperty(key)) {    //是否是自身的对象            newObj[key] = deepClone(obj[key])   //赋值        }    }    return newObj}const copyObj = deepClone(obj);obj.others.team = 'Lakers';console.log(obj,copyObj)复制代码
           

模拟call、apply、bind实现

Function.prototype.myCall = function (context) {  var context = context || window  // 给 context 添加一个属性  // getValue.call(a, 'yck', '24') => a.fn = getValue  context.fn = this  // 将 context 后面的参数取出来  var args = [...arguments].slice(1)  // getValue.call(a, 'yck', '24') => a.fn('yck', '24')  var result = context.fn(...args)  // 删除 fn  delete context.fn  return result}Function.prototype.myApply = function (context) {  var context = context || window  context.fn = this  var result  // 需要判断是否存储第二个参数  // 如果存在,就将第二个参数展开  if (arguments[1]) {    result = context.fn(...arguments[1])  } else {    result = context.fn()  }  delete context.fn  return result}Function.prototype.myBind = function (context) {  if (typeof this !== 'function') {    throw new TypeError('Error')  }  var _this = this  var args = [...arguments].slice(1)  // 返回一个函数  return function F() {    // 因为返回了一个函数,我们可以 new F(),所以需要判断    if (this instanceof F) {      return new _this(...args, ...arguments)    }    return _this.apply(context, args.concat(...arguments))  }}复制代码
           

快速、希尔、归并排序

// 快速排序function quickSort(arr) {  if (arr.length <= 1) {      return arr;  }  var pivotIndex = Math.floor(arr.length / 2);  var pivot = arr.splice(pivotIndex, 1)[0];  var left = [];  var right = [];  for (var i = 0; i < arr.length; i++) {      if (arr[i] < pivot) {          left.push(arr[i]);      } else {          right.push(arr[i]);      }  }  return quickSort(left).concat([pivot], quickSort(right));};// 希尔排序function shellSort(arr) {  for(let gap = Math.floor(arr.length/2); gap > 0; gap = Math.floor(gap/2)) {    // 内层循环与插入排序的写法基本一致,只是每次移动的步长变为 gap    for(let i = gap; i < arr.length; i++) {      let j = i;      let temp = arr[j];      for(; j> 0; j -= gap) {        if(temp >= arr[j-gap]) {          break;        }        arr[j] = arr[j-gap];      }      arr[j] = temp;    }  }  return arr;}// 归并排序function mergeSort(arr) {    var len = arr.length;    if(len < 2) {        return arr;    }    var middle = Math.floor(len / 2),        left = arr.slice(0, middle),        right = arr.slice(middle);    return merge(mergeSort(left), mergeSort(right));}function merge(left, right){    var result = [];    while (left.length && right.length) {        if (left[0] <= right[0]) {            result.push(left.shift());        } else {            result.push(right.shift());        }    }    while (left.length)        result.push(left.shift());    while (right.length)        result.push(right.shift());    return result;}复制代码
           

数组去重

[...new Set([1,2,3,1,'a',1,'a'])][1,2,3,1,'a',1,'a'].filter(function(ele,index,array){    return index===array.indexOf(ele)})复制代码
           

Proxy使用get拦截,实现数组读取负数的索引

function createArray(...elements) {  let handler = {    get(target, propKey, receiver) {      let index = Number(propKey);      if (index < 0) {        propKey = String(target.length + index);      }      return Reflect.get(target, propKey, receiver);    }  };  let target = [];  target.push(...elements);  return new Proxy(target, handler);}let arr = createArray('a', 'b', 'c');arr[-1] // c复制代码
           

Promise的实现

class Promise{  constructor(executor){    this.state = 'pending';    this.value = undefined;    this.reason = undefined;    this.onResolvedCallbacks = [];    this.onRejectedCallbacks = [];    let resolve = value => {      if (this.state === 'pending') {        this.state = 'fulfilled';        this.value = value;        this.onResolvedCallbacks.forEach(fn=>fn());      }    };    let reject = reason => {      if (this.state === 'pending') {        this.state = 'rejected';        this.reason = reason;        this.onRejectedCallbacks.forEach(fn=>fn());      }    };    try{      executor(resolve, reject);    } catch (err) {      reject(err);    }  }  then(onFulfilled,onRejected) {    // 声明返回的promise2    let promise2 = new Promise((resolve, reject)=>{      if (this.state === 'fulfilled') {        let x = onFulfilled(this.value);        // resolvePromise函数,处理自己return的promise和默认的promise2的关系        resolvePromise(promise2, x, resolve, reject);      };      if (this.state === 'rejected') {        let x = onRejected(this.reason);        resolvePromise(promise2, x, resolve, reject);      };      if (this.state === 'pending') {        this.onResolvedCallbacks.push(()=>{          let x = onFulfilled(this.value);          resolvePromise(promise2, x, resolve, reject);        })        this.onRejectedCallbacks.push(()=>{          let x = onRejected(this.reason);          resolvePromise(promise2, x, resolve, reject);        })      }    });    // 返回promise,完成链式    return promise2;  }}function resolvePromise(promise2, x, resolve, reject){  // 循环引用报错  if(x === promise2){    // reject报错(检测到promise的链接循环)    return reject(new TypeError('Chaining cycle detected for promise'));  }  // 防止多次调用  let called;  // x不是null 且x是对象或者函数  if (x != null && (typeof x === 'object' || typeof x === 'function')) {    try {      // A+规定,声明then = x的then方法      let then = x.then;      // 如果then是函数,就默认是promise了      if (typeof then === 'function') {         // 就让then执行 第一个参数是this   后面是成功的回调 和 失败的回调        then.call(x, y => {          // 成功和失败只能调用一个          if (called) return;          called = true;          // resolve的结果依旧是promise 那就继续解析          resolvePromise(promise2, y, resolve, reject);        }, err => {          // 成功和失败只能调用一个          if (called) return;          called = true;          reject(err);// 失败了就失败了        })      } else {        resolve(x); // 直接成功即可      }    } catch (e) {      // 也属于失败      if (called) return;      called = true;      // 取then出错了那就不要在继续执行了      reject(e);     }  } else {    resolve(x);  }}复制代码
           

如果你现在也想学习前端开发技术,在学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,你都可以申请加入我的Q群:前114中6649后671,里面有许多前端学习资料 大厂面试真题免费获取,希望能够对你们有所帮助。

前端为什么有的接口明明是成功回调却执行了.catch失败回调_想知道前端面试如何手写模拟实现吗?...模拟call、apply、bind实现快速、希尔、归并排序数组去重Proxy使用get拦截,实现数组读取负数的索引Promise的实现
前端为什么有的接口明明是成功回调却执行了.catch失败回调_想知道前端面试如何手写模拟实现吗?...模拟call、apply、bind实现快速、希尔、归并排序数组去重Proxy使用get拦截,实现数组读取负数的索引Promise的实现