一、手写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的实参,
新函数执行的时候,给新函数的实参会拼到原来实参的后面