资讯专栏INFORMATION COLUMN

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

iKcamp / 1407人阅读

摘要:目录一理解指针意义二用解决指针指向问题三的使用场景与少用之处一理解指针意义让我们先理解好指针的定义引用的是函数执行的环境对象永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的通俗地讲,就是谁调用,就指向谁我们分类举例举例前先看下本

目录

一.理解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/10...

以上是部分this指针的理解

如果我在事件监听中想要减少代码重复,或者是调用其他对象的属性呢?

如果我想用btn.addEventListener()时指向的某个特定对象呢?

这就可以引出下面call(),apply()与bind()的应用了

7.函数中自执行函数指向
function User(id){
    this.id = id;
}
User.prototype.test = function(){
    console.log(this);//指向b对象

   (function(){
    console.log(this) //指向window
})()
}
var a = new User("a")
a.test(); 

因为自执行函数是由window执行的
如果此时使用箭头函数

function User2(id){
    this.id = id;
}
User.prototype.test = function(){
    console.log(this); //指向b对象

   (() =>{
    console.log(this) //指向b对象
})()
}
var b = new User2("b");
b.test(); 

因为箭头函数不会绑定this,所以指向上一层的b对象

二.用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]是传参示例
};
弹出"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/...

    MDN:bind():    https://developer.mozilla.org...

    MDN:apply():https://developer.mozilla.org...

    MDN:call():    https://developer.mozilla.org...

    《JavaScript高级程序设计(第3版)》

    《JavaScript语言精粹》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108554.html

相关文章

  • javascript基础:this关键字

    摘要:它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用类似的还有。总结关键字就是,谁调用我,我就指向谁。注意由于已经被定义为函数内的一个变量。因此通过关键字定义或者将声明为一个形式参数,都将导致原生的不会被创建。 题目 封装函数 f,使 f 的 this 指向指定的对象 。 输入例子 bindThis(function(a, b) { return this.test +...

    LeoHsiun 评论0 收藏0
  • 你不知道javascript(上卷)读后感(二)

    摘要:词法熟悉语法的开发者,箭头函数在涉及绑定时的行为和普通函数的行为完全不一致。被忽略的作为的绑定对象传入,使用的是默认绑定规则。使用内置遍历数组返回迭代器函数普通对象不含有,无法使用,可以进行改造,个人博客地址 this词法 熟悉ES6语法的开发者,箭头函数在涉及this绑定时的行为和普通函数的行为完全不一致。跟普通this绑定规则不一样,它使用了当前的词法作用域覆盖了this本来的值。...

    Ali_ 评论0 收藏0
  • JavaScript函数callapplybind

    摘要:它们有明确的和成员函数的定义,只有的实例才能调用这个的成员函数。用和调用函数里用和来指定函数调用的,即指针的指向。同样,对于一个后的函数使用或者,也无法改变它的执行,原理和上面是一样的。 函数里的this指针 要理解call,apply和bind,那得先知道JavaScript里的this指针。JavaScript里任何函数的执行都有一个上下文(context),也就是JavaScri...

    alighters 评论0 收藏0
  • bind()、call()、apply()理解用法

    摘要:首先,我们判断是否存在方法,然后,若不存在,向对象的原型中添加自定义的方法。指向调用它的对象。总之三个的使用区别都是用来改变函数的对象的指向的第一个参数都是要指向的对象都可以利用后续参数传参是返回对应函数,便于稍后调用,是立即调用 apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向),Function对象的方法,每个函数都能调用; 使用a...

    hoohack 评论0 收藏0
  • 2019面试笔记

    摘要:使用构造函数创建对象后,新对象与构造函数没有关系了,新对象的属性指向的是构造函数的原型对象。构造继承使用父类的构造函数来增强子类的实例,等于是在子类的构造函数内部执行。 一.js原始类型: 在js中,存在着6种原始值: * boolean * number * string * undefined * null * symbol 注意: 虽然typeof null输出的是o...

    nidaye 评论0 收藏0

发表评论

0条评论

iKcamp

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<