前端每日一道手写题

81 阅读2分钟

不分块了,太容易乱了,写到哪算哪吧

1.手写 call/apply/bind

  • call
  • 参数:(obj,...args)
  • 特点:支持多个参数
Function.prototype.myCall = function(obj,...args){
    //将obj的上下文存入context
    const context = obj;
    //设置一个独一无二的Symbol变量,避免覆盖原obj对象中方法
    const func = Symbol;
    //将Function(也就是xxx.myCall中xxx函数存储进func中)
    context[func] = this;
    //myCall调用获取结果,此刻是在obj内调用对象,满足call
    const res = context[func](...args);
    //返回结果
    return res;
}
  • apply
  • 与myCall写法差不多,区别仅在与传入的参数,call支持传入多个参数,而apply仅支持传入obj与arg(数组)
  • 参数:(obj,args)
//与myCall区别不大,仅在args方面有区别
Function.prototype.myApply = function(obj,args){
    const context = obj;
    const func = Symbol();
    context[func] = this;
    const res = context[func](args);
    return res;
}
  • bind
  • 区别:与call、apply不同的是,bind返回的是一个函数,手写时,内部用到call或apply
  • 参数:arguments
Function.prototype.myBind = function(){
    //第一步:将参数转换为数组
    const args = Array.prototype.slice.call(arguments);
    //第二步:获取args中的对象上下文(位于args数组第一位)
    const context = args.shift();
    //第三步:保存本函数的this
    const self = this;
    //第四步:返回一个函数,函数中调用该函数
    return function(){
        return self.apply(context,args);
    }
}

//使用示例:
function con(a,b){
    console.log(this,a,b)
}

(con.myBind({name:"Tom"},1,2))();

2.Ajax

  • 通过XMLHttpRequest实现
const doAjax = function(url){
    return new Promise((resolve,reject)=>{
      const xhr = new XMLHttpRequest();
      //xhr配置
      xhr.open('GET',url,false)//false表示非异步
      xhr.setRequestHeader("Accept","application/json");
      //Ajax状态改变时运行回调
      xhr.onreadystate = function(){
          if( xhr.readystate !== 4 ) return; //状态码不为4说明请求不成功
          //请求成功
          if( xhr.status === 200 || xhr.status === 304){
              resolve(xhr.responseText);
          }else{
              reject(new Error(xhr.responseText))
          }
      }
    })
    xhr.send();
}

3.new关键字

原理:创建一个空对象 → 将空对象的隐式原型__proto__指向构造函数的原型prototype → 让空对象进行继承 → 返回结果(若无返回值,则返回对象,否则返回res

function myNew(func,...args){
    let obj = {};
    //修改原型链
    obj.__proto__ = func.prototype;
    const res = func.call(obj,...args);
    if( typeof res === "object" || typeof res === "function" ) return res;
    return obj;
}