手写call:
Function.prototype.ownCall=function(newObj,...args){ if(typeof newObj=='function'){ throw new TypeError('type error'); } let fn=Symbol('fn');//唯一值,保证不会覆盖函数原属性 newObj=newObj||window //如果没有传入对象则绑定到window newObj[fn]=this//把函数绑定到传入对象的某个属性 let result=newObj[fn](...args);//调用传入对象的参数返回结果 delete newObj[fn] //删除函数声明 return result; } function showName(){ console.log(this.name); } var db={ name:'zhangsan' } showName.ownCall(db);
手写apply(和call类似,只是传入参数类型不同:一个是逗号分割的字符串,一个是数组)
Function.prototype.ownApply=function(newObj,args){ if(typeof newObj=='function'){ throw new TypeError('type error'); } //唯一值,防止属性覆盖 let fn=Symbol('fn'); //如果没有则赋值给window newObj=newObj||window; //把函数赋值到新对象的某个属性 newObj[fn]=this //调用传入对象的参数返回对象 let result=newObj[fn](...args); delete newObj[fn] return result; }; function showName(){ console.log(this.name); } let db={ name:'lisi' } showName.apply(db);
手写bind:
//考虑返回的函数作为构造函数使用的情况,这是绑定函数中this指向构造函数自身,并且绑定函数原型也和构造函数原型相同 Function.prototype.ownBind=function(newObj,...args){ if(typeof newObj=='Function'){ throw new TypeError('type error'); } let _self=this function fnBound(){ //如果绑定函数中this和构造函数this相同,则判定是new let _this=this instanceof _self?this:newObj //把绑定对象和传入参数传入原函数 return _self.apply(_this,args.concat([].slice.apply(arguments,[0]))) }
let fn=function(){} if(this.prototype){ fn.prototype=this.prototype fn.prototype.constructor=this }
fnBound.prototype=new fn(); return fnBound; }
function sum(name){
this.name=name;
}
let obj={}
let output=sum.ownBind(obj);
output('zhangsan');
console.log(obj.name);
let o=new output('lisi');
console.log(obj.name);
console.log(o.name);