this指针使用及call(),apply()及bind()的使用

目录

一.理解this指针意义

二.用call(),apply(),bind()解决指针指向问题

三.bind()的使用场景与少用之处


一.理解this指针意义


让我们先理解好this指针的定义:
this引用的是函数执行的环境对象
this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的

通俗地讲,就是谁调用this,this就指向谁,我们分类举例

举例前先看下本文会一直用到的变量及定义的函数

var theName = "Joe";    //全局变量

function showName() {
   var theName = "Li";
   alert(this.theName);
}


1.全局直接调用方法

showName();    //弹出“Joe”
因为是window对象调用showName(),所以this指向window啦,故弹出"Joe"


2.对象中调用全局下的方法

var student1 = {
   theGrade : 100,
   theName : "Han",
   showName : showName,
   showGrade : function () {
      alert(this.theGrade);
   }
};
student1.showName();//弹出“Han”
student1.showGrade();//弹出“100”
因为是在student1对象调用函数,故弹出的是对应student1对象中的"Han"和“100”啦


3.对象中调用其他对象的方法

var student2 = {
   theGrade: 60,
   showGrade: student1.showGrade
};
student2.showGrade();    //弹出"60"
即使student2对象调用了student1对象下的方法showGrade(),因为是student2对象调用,故弹出的仍是student2的"60"

4.对象的方法赋给全局变量执行

var outFunction = student1.showGrade;
outFunction();//弹出“undefined”
将sutdent1对象的函数赋值给oufFuncction,而outFunction是在window对象下调用的,故弹出“undefined”



5.构造函数下的this指针

function setStudent() {
   this.theName = "Ming";
}
var student3 = new setStudent();
alert(student3.theName);//弹出“Ming”,new改变this指向
构造函数下,new改变了指针指向,指向了student3


6.事件监听中创建闭包的this指针

关键:闭包保存创建时的环境!!!

举个例子
为了更好理解闭包与指针的关系,我们先定义一个全局变量,一个函数,和一个对象

var example = 'window';//全局变量

function showExample() {
   console.log(this.example);
}

var exampleObject = {
   example : 'Object',
   showExample_in_Object : function (arg1, arg2) {
      console.log(this.example);
      console.log(arg1,arg2)
   }
};

接着,我们设置一个事件监听来说明问题:

//事件监听
var btn = document.getElementById("btn");
btn.onclick = function (ev) {
   console.log(this); //this指向按钮,执行匿名函数的是btn
   this.example = 'ele';
   console.log(this.example);//弹出"ele"
   showExample(); //闭包保存函数创建时的环境,故this指向window对象 
   exampleObject.showExample_in_Object();//this指向exampleObject
};
结果:
接下来分段说明各个指针
其中
    this.example = 'ele';
    console.log(this.example);
其中的this指向btn,所以显示的是‘ele’

    showExample();      
    exampleObject.showExample_in_Object();    
匿名函数中为闭包,闭包保存函数创建时的环境,故this分别指向window和exampleObject

补充对闭包中this的理解:https://segmentfault.com/q/1010000004648772


以上是部分this指针的理解


如果我在事件监听中想要减少代码重复,或者是调用其他对象的属性呢?
如果我想用btn.addEventListener()时指向的某个特定对象呢?
这就可以引出下面call(),apply()与bind()的应用了


二.用call(),apply(),bind()解决指针指向问题


1.call()与apply()


call()与apply()的作用都是在特定的作用域中调用函数,实际上等于设置函数体内设置this对象的值
简单地说,就是可以改变函数的执行环境
call()与allpy()效果相同,仅是传参形式不同,如下所示

call():
fun.call(thisArg, arg1, arg2, ...)

thisArg : fun函数运行时指定的this值
arg1,arg2,.. (可选):指定的各个参数

apply():
func.apply(thisArg, [argsArray])
thisArg : fun函数运行时指定的this值
[argsArray](可选) : 传参数组或者传参类数组


下面直接看例子吧
我们以上面的例子进行修改,为了对比传参的形式,我们对showExample函数添加两个参数
function showExample(arg1,arg2) {
   console.log(this.example);
   console.log(arg1,arg2);
}

接下来便是btn的点击事件函数修改,我们令showExample函数指向exampleObject
//call与apply的应用
btn.onclick = function (ev) {
   showExample.call(exampleObject,111,222); //弹出'Object' ,111与222是传参示例
   showExample.apply(exampleObject,[111,222]); //弹出'Object' ,[111,222]是传参示例
};

如上,通过call()与apply()的应用,可以改变函数的指向而多次运用


如果我想便于调试想使用ele.addEventListener()嘞?
这就要用上bind()方法了

2.bind()的运用

fun.bind(thisArg[, arg1[, arg2[, ...]]])
MDN : bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值, ,在调用新函数时,在任何提供之前提供一个给定的参数序列。


我们再举个简单的例子,将exampleObject简单修改下
var exampleObject = {
   example : 'Object',
   showExample_in_Object : function (arg1, arg2) {
      console.log(this);
      console.log('example:'+ this.example);
      console.log('arg1:' + arg1);
      console.log('arg2:' + arg2);
   }
};


并把showExample_in_Object()函数添加给btn
注意这里的是函数,不是闭包!

btn.addEventListener('click',exampleObject.showExample_in_Object);
控制台显示如下
            
可以看出this指向的是btn,而无法满足我们使用exampleObject中属性的需要,同时也无法进行传参(用call()与apply()就直接执行函数了!)
(这里的没有对第一个参数arg1进行传参,故默认显示MouseEvent对象)


这时我们可以用bind()方法创建一个新的函数,并让其指针指向exampleObject,并传两个新的参数进去

btn.addEventListener('click',exampleObject.showExample_in_Object.bind(exampleObject,111,222));

当当~指针指向了exampleObject,传参也成功了~

另外,这里也有个可以不使用bind()的方法,就是也用闭包
btn.addEventListener('click',function () {
    exampleObject.showExample_in_Object(111,222);
});

结果一样,但这种方法不利于代码的维护,同时也无法指向特定的对象    

三.bind()的使用场景与少用之处


使用场景:主要用于如上的事件监听,以及setTimeout()和setInterval()

少用之处:被绑定的函数与普通函数相比有更多的开销,它们需要更多的内存,同时也因为多重函数调用稍微慢一点,所以最好只在必要时使用

以上,如有不对之处,请大家指教~

参考资料:
    彻底理解this指针:     https://www.cnblogs.com/pssp/p/5216085.html
    《JavaScript高级程序设计(第3版)》
    《JavaScript语言精粹》



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值