~
- bind会返回一个硬绑定的新函数,新函数会使用指定的第一个thisCtx去调用原始函数,并将其它参数传给原始函数。 硬绑定会降低函数的灵活性,在绑定之后不能通过显式或硬绑定的方式改变this,只能通过new改变
- softBind 会对指定的函数进行封装,首先检查调用时的 this,如果 this 绑定到全局对象或者 undefined,那就用指定的thisCtx 去调用函数,否则不会修改 this
- apply和call功能相同,都是以指定的thisCtx和参数去执行方法,并返回原方法的返回值,只是apply中参数以数组传递
bind()函数
bind 函数用于绑定this关键字,改变this指向,并且最终返回一个函数
用法: function.bind(thisArg,arg1,arg2,arg3,...)
例子:
function add(x,y){
// console.log("yhis",this)
return x+y;
}
function newArrBind(x,y){
let bindAddFn=add.bind(this,x,y);
// console.log("this",this)
return bindAddFn()
}
console.log(newArrBind(10,20))//30
手动实现
//bind()实现
console.log("bind()函数的实现")
Function.prototype.newBind=function(obj,...args){
return (...res)=>this.call(obj,...args,...res);
}
function func(arg){
console.log("num:",this.num,"arg:",arg);
}
func.bind({num:999})(123);
//num: 999 arg: 123
func.newBind({num:999})(123);
//num: 999 arg: 123
关于softbind()软绑定
在了解softbind之前先看之前的例子带有//+的为增加的代码
案例
Function.prototype.newBind=function(obj,...args){
return (...res)=>this.call(obj,...args,...res);
}
function func(arg){
//+
console.log("this=>",this)
console.log("num:",this.num,"arg:",arg);
}
//+
func("啦啦啦~")
//输出 this=> Window {window: Window, self: Window, document: document, name: '', location: Location, …}
// num: undefined arg: 啦啦啦~
func.bind({num:999})(123);
//this=> {num: 999}
//num: 999 arg: 123
func.newBind({num:999})(123);
// this=> {num: 999}
//num: 999 arg: 123
func.bind({num:999}).call({num:888},777)
// this=> {num: 999}
// index.js:9 num: 999 arg: 777
func.bind({num:999}).bind({num:666})(555);
// this=> {num: 999}
// index.js:9 num: 999 arg: 555
可以看到这个时候this指向已经被写死了,事实上,bind函数多次调用会已第一次绑定的this为准,softbind已最后一次绑定传入的this为准;
手动实现
Function.prototype.softBind=function(obj,...rest){
const fn=this;
const bound=function(...args){
const o=!this || this===(window || global) ? obj : this;
return fn.apply(o,[...rest,...args]);
}
bound.prototype=Object.create(fn.prototype);
return bound;
}
func.softBind({num:999})(888);
// this=> {num: 999}
// index.js:9 num: 999 arg: 888
func.softBind({num:888})(777);
// this=> {num: 888}
// index.js:9 num: 888 arg: 777
call函数
call函数调用一个杉树时,会将该函数的执行对象的上下文改变为另一个对象
函数用法: function.call(thisArg,arg1,arg2,...)
例子
function add(x,y){
return x+y;
}
function myAddCall(x,y){
return add.call(this,x,y);
}
console.log(myAddCall(10,20));//输出30
手动实现
function func(arg){
//+
console.log("this=>",this)
console.log("num:",this.num,"arg:",arg);
}
//+
func("啦啦啦~")
Function.prototype.newCall=function(ctx=globalThis){
const args=Array.from(arguments).slice(1);
const key=Symbol("key");
ctx[key]=this;
const res=ctx[key](...args);
delete ctx[key];
return res;
}
func.call({num:333},444)
func.newCall({num:111},222)
// index.js:8 this=> Window {window: Window,
//self: Window, document: document, name: '', location: Location, …}
// index.js:9 num: undefined arg: 啦啦啦~
// index.js:8 this=> {num: 333}
// index.js:9 num: 333 arg: 444
// index.js:8 this=> {num: 111, Symbol(key): ƒ}
// index.js:9 num: 111 arg: 222
apply()函数
apply函数作用域与call函数是一样的,只是在传递参数的形式上存在差别。
语法格式: function.apply(thisArg,[argsArray])
案例
function add(x,y){
return x+y;
}
function myAddApply(x,y){
return add.apply(this,[x,y]);
}
console.log(myAddApply(10,20))//30
手动实现
Function.prototype.newApply = function (ctx = globalThis) {
const args = arguments[1];
const key = Symbol("key");
ctx[key] = this;
const res=ctx[key](...args);
delete ctx[key]
return res
};
func.apply({num:777},[888]);
// this=> {num: 777}
// index.js:9 num: 777 arg: 888
func.newApply({num:777},[888]);
// {num: 777, Symbol(key): ƒ}
// index.js:9 num: 777 arg: 888