深入理解javascript中bind、apply、call
相信做过一段时间的javascript开发的同学都或多或少用过或者见到过bind、apply、call方法。他们的作用很简单,就是改变执行函数的this指向,如果您对this了解比较模糊,您可以看这一篇博客。
作用
首先,我们了解下,改变执行函数的this指向有哪些作用,对我们开发有哪些好处。同样,我们从一个例子开始吧。
const obj = { name: '张三', age: 18, introduction: function() { console.log(`my name is ${this.name}, i am ${this.age} years old`) } } obj.introduction(); //my name is 张三, i am 18 years old obj.introduction.apply({name: '李四', age: 22}); //my name is 李四, i am 22 years old
例子中,张三有一个introduction可以介绍他的信息,所以当调用obj.introduction()时,可以打印张三的个人信息,后面,我们将obj.introduction()方法绑定在了对象{name: '李四', age: 22}上,从而改变了this指向,最终打印了李四的个人信息。
由此,我们可以看出通过改变this指向,我们可以实现代码复用。
异同
了解了改变this指向的作用后,我们发现bind、apply、call都是可以改变this指向,那它们有何不同之处呢,下面我们讨论下。
1. bind
bind方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,值得注意的是bind方法的返回值仍然是一个方法,我们需要添加一对小括号才能让他执行。请看使用实例。
const obj = { name: '张三', age: 18, introduction: function(sex) { console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`) } } const bindFunc = obj.introduction.bind({name: '王五', age: 21}, 'men'); bindFunc(); //my name is 王五, i am 21 years old, my sex is men
2. apply
apply方法第一个参数是需要绑定的对象,第二个参数是一个数组,数组中的元素为改变this指向方法的参数,和bind不同的是,此时函数会立即执行。请看实例。
const obj = { name: '张三', age: 18, introduction: function(sex) { console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`) } } obj.introduction.apply({name: '李四', age: 22}, ['men']); //my name is 李四, i am 22 years old, my sex is men
3. call
call方法和apply方法极为相似,方法第一个参数是需要绑定的对象,后面的参数是改变this指向方法的参数,同样,函数也是立即执行。请看实例。
const obj = { name: '张三', age: 18, introduction: function(sex) { console.log(`my name is ${this.name}, i am ${this.age} years old, my sex is ${sex}`) } } obj.introduction.call({name: '周六', age: 19}, 'men'); //my name is 周六, i am 19 years old, my sex is men
关于他们的异同,这里总结了一个表格。
相信了解他们的用法是一个比较简单的事儿。不过,作为一个励志成为一个更优秀(tutou)的程序yuan,刨根问底是一个优良品质。
下面,我们来分别实现这三个方法。
1. myBind
程序实现
function myBind(ctx, ...rest) { const context = ctx || window; const _this = this; return function() { context.fn = _this; context.fn(...rest); delete context.fn; } } Function.prototype.myBind = myBind;
2. apply
程序实现
function myApply(ctx, params) { const context = ctx || window; ctx.fn = this; ctx.fn(...params); delete ctx.fn; }
3. call
程序实现
function myCall(ctx, ...rest) { const context = ctx || window; context.fn = this; context.fn(rest); delete context.fn; } Function.prototype.myCall = myCall;
相信上面的代码聪明的你一眼就看懂了。bind、call、apply三个方法的实现原理都是一样的,只是让我们可以通过不同的方式使用它。
他们改变this指向的原理是通过 将需要改变this指向的方法附加在对象中执行,则方法中的this就会指向附加的对象。(在方法中,this 表示该方法所属的对象。)
浅陋见识,不足之处,请大神指正。