Js中bind方法使用和实现
前面我们已经模拟实现了call和apply方法,今天来实现下同样可以改变this指向但是又有点不同得方法--> bind方法。
定义
首先来看下bind方法在mdn中得定义,bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
语法
function.bind(thisArg[, arg1[, arg2[, ...]]])
参数
thisArg 调用绑定函数时作为 this 参数传递给目标函数的值。 如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg《医院证明模板》。
arg1, arg2, ... 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
返回值
返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
从上面mdn中得描述中我们看到bind方法和call、apply方法得不同点就是,bind方法同样是将调用函数得this指向第一个参数,但是这个时候不会执行函数,而是会创建一个新的函数并返回出来,除了第一个参数剩下得参数传入新返回得函数使用。并且返回的函数还可以被new操作符进行调用,使用new操作符时bind方法传入得第一个this指向得值就失效了,此时函数this得指向遵循new操作符的this指向原则。(new操作符解析)。
使用
function say(res, res2) {
this.num = res;
console.log(this);
console.log(this.hello);
console.log(res);
console.log(res2);
}
let obj = {
hello: 'hello'
}
const back = say.bind(obj, 1);
back(3);
// {hello: "hello", num: 1}
// hello
// 1
// 3
上述代码由打印值可以看出,利用bind函数将say函数内部的this指向了obj对象,并且为obj对象添加了一个属性num赋值为1,并且bind函数返回的back函数传入的参数在bing函数传入参数的后面进行传入。但是没有使用new操作符,接下来看使用new操作符调用back函数。
function say(res, res2) {
this.num = res;
console.log(this);
console.log(this.hello);
console.log(res);
console.log(res2);
}
let obj = {
hello: 'hello'
}
const back = say.bind(obj, 1);
const b = new back(6);
console.log(b, 'b')
// say {num: 1}
// undefined
// 1
// 6
// say {num: 1} "b"
上述代码将bind函数返回的back函数使用new操作符调用,看打印结果将say函数的this指向了new操作符生成的实力对象b上。下面我们就根据规则实现模拟实现自己的bind操作符。
实现思路
1、 在Function的原型上添加自己的bind方法
2、 返回一个新的函数backFn
3、 判断函数是不是由new操作符调用
4、 是的话将this指向生成的实力对象,不是的话将this指向传入的第一个值
5、 如果原函数存在原型对象,将返回函数backFn的原型指向原来函数的原型对象(因为bind返回的函数相当于原函数的复制)
6、 返回backFn函数
实现
// 添加bind方法,并传入参数
Function.prototype.myBind = function (thisArg, ...bindRes) {
// 将函数保存起来
const thisFn = this;
if (typeof thisFn !== 'function') {
throw new TypeError(this + 'is not a function');
}
const backFn = function (...backRes) {
// 判断是否是new操作符调用,是的话采用生成的实例对象(因此时backFn函数this就指向实例对象所以直接指向this即可)
// 参数传入如果是es5实现可以使用arguments对象
// 使用之前自己写好apply方法改变this指向
if (new.target) {
return thisFn.apply(this, [...bindRes, ...backRes]);
} else {
return thisFn.apply(thisArg, [...bindRes, ...backRes]);
}
// 或者也可以这样子写
// return thisFn.apply(new.target? this: thisArg, [...bindRes, ...backRes]);
}
// 采用创建空函数的方法,将bacnFn函数原型指向原函数防止改变bacnFn函数原型对象而影响原函数原型对象
if (thisFn.prototype) {
const emptFn = function () {};
emptFn.prototype = thisFn.prototype;
backFn.prototype = new emptFn();
}
return backFn;
}
测试
function say(res, res2) {
this.num = res;
console.log(this);
console.log(this.hello);
console.log(res);
console.log(res2);
}
say.prototype.str = '内容'
let obj = {
hello: 'hello'
}
const back = say.myBind(obj, 1);
back(3);
// {hello: "hello", num: 1}
// hello
// 1
// 3
const b = new back(6);
console.log(b.str, 'b')
// backFn {num: 1}
// undefined
// 1
// 6
// 内容 b
测试结果符合期望结果,至此我们自己的bind方法就实现了。
来源:http://www.chiniurou.com/tupian/493.html
标签:console,函数,bind,js,new,方法,hello,log From: https://www.cnblogs.com/bkycnd/p/16736589.html