简简单单手写五种类

110 阅读2分钟

一、手写instanceof

<script>
let ary = [];
console.log(ary instanceof Array)//通过原型中查找Array中有没有ary属性有就是true没有fales
function myInstanceof(a,b){
let item = a.__proto__ //把a的原型赋值给item
 while(item&&time!=b.prototype){    //循环(条件:item存在并且不等于b的原型,如果item不存在(值为null)或item在b的原型中的时候跳出循环
 tiem = item.__proto__;    //在item原型链中查找直到找到或者__proto__为null
 }
 if(item==null){
   return false     //判断如果tiem为null返回false,否则为true
 }else{
 return true   
 }
}
console.log(myInstanceof(ary,Array)//true
console.log(myInstanceof({},Array)//false
</script>

二、手写new

<script>
 function myNew(a,...args){   //...是展开运算符
 let obj = {};
 obj.__proto__ = a.prototype; //把a函数的原型赋值给obj所属类的原型
 let  res = a.call(obj,...args); //把a函数的this指向obj
 retrun typeof res==`object`?res:obj //返回值如果是引用数据类型就返回res,如果不是就返回obj(new中的this)
 }
 function Person (name,age,sex){
 this.name = name;
 this.age = age;
 this.sex = sex;
 }
 let p1 = new Person('小康'12,1);//new 执行的时候会开辟一个堆,然后把函数中的this指向这个堆
 let p2 = myNew(Person,'小康'12,1);
</script>

三、手写call

第一种 不管fn的冲突问题

fanction fn (q,w,e){
console.log(this);
console.log(q,w,e);
return 666
let obj = {
name:'我是大帅比'
}
Function.prototype.myCall = function(key,...arg){
    key.fn = this; //把this指向赋值给key.fn
    retrun key.fn(...arg)
}
let res = fn.call(obj,1,2,3) //call执行会把fn的this指向obj,后面的参数都是传给fn函数的实参
let res2 = fn.myCall(obj,1,2,3)

第二种 考虑fn的冲突问题例如

fanction fn (q,w,e){
console.log(this);
console.log(q,w,e);
return 666
let obj = {
name:'我是大帅比'fn:888
}
Function.prototype.myCall = function(key,...arg){
    let a = Symbol('myCall'); //创建唯一值给一个变量a
    key[a] = this;  //把this给key[a]
    delete key[a];  //删除唯一值
    let res = key[a](...arg) //把执行结果用一个变量装起来,这边变量就是这个函数的返回值
    
    return res
}
let res = fn.call(obj,1,2,3) //call执行会把fn的this指向obj,后面的参数都是传给fn函数的实参
let res2 = fn.myCall(obj,1,2,3)

四、手写apply

apply和call 功能一样,区别在于call执行的时候传的实参是散开的,apply中传的实参是一个集合的方式如:

f.call(obj,1,2);

f.apply(obj,[1,2])

Function.prototype.myApply = function(key,arg){ //因为传的实参是一个集合所以形参不需要...展开
 let fn = this; //this 给 fn 方法基本和call一样
 let a = Symbol('myApply');
 let res = key[a](...arg);
 delete key[a] //删除唯一值
 return res
}

五、手写bind

function fn() {
        console.log(arguments);
        console.log(this);
    }
    var obj = {
        name: '珠峰'
    }
    Function.prototype.myBind = function(key,...arg){
    let fn = this  //把this给fn
    return function (...arg2){   //返回的是一个新的函数
        return fn.call(key,...arg,...arg2)
      }
    }
   let res = fn.bind(obj,1,2,3) 
   res(4,5,6)
   // bind执行的返回值是一个新函数,
   新函数执行的时候fn执行,并且把fn中的this指向obj,后面的参数是给fn的实参,
   新函数执行的时候,给新函数的实参会拼到原来实参的后面