javascript 中经典的call 、apply、bind方法以及this指向详解

前言

一说到js中的call、apply、bind方法,就一定会和this联系起来,百分之九十以上的问题都是有关这三个函数方法中this的指向问题,在前端面试题中非常的常见,掌握了这三个方法的this指向问题,不仅可以在面试官前侃侃而谈,加深面试官对你的印象,而且可以提高我们js代码的编码水平和编码水平,作为一个前端这是我们必须掌握的基本知识。 再说他们三个之前,我们先来说下this吧,懂了this的指向问题,也就掌握了这三个方法的精髓。

this

this是函数内部的一个特殊的对象,,this引用的是函数据以执行的环境对象——或者也可以说是this值(当在网页的全局作用域调用函数时,this 对象引用的就是 window )。简单的说this指向调用该函数的环境对象。再简单一点就是谁调用它就指向谁,下面具体的说说this的调用指向

1.纯函数调用
var x = 1;
function test() {
   console.log(this.x);
}
test();  // 1  this指向全局对象
复制代码
2.作为对象的方法调用
var obj = {
        n:'1',
    m:function test() {
  console.log(this.n);
}
         };
obj.m()//1 this指向obj
复制代码
3.作为构造函数调用
var x = 2;
function Test() {
 this.x = 1;
}

var obj = new Test();
obj.x // 1 this 指向obj
x=2 //说明this并不是指向的是window
复制代码
4.事件绑定中的this

备注:下面的两个this指向参考了这个作者的文章,在通读之后觉得写的很透彻明了,就直接节选了部分,自己也就不在罗嗦了。

链接:zhuanlan.zhihu.com/p/42145138

事件绑定共有三种方式:行内绑定、动态绑定、事件监听;行内绑定的两种情况:

<input type="button" value="按钮" onclick="clickFun()">
<script>
    function clickFun(){
        this // 此函数的运行环境在全局window对象下,因此this指向window;
    }
</script>
​
<input type="button" value="按钮" onclick="this">
<!-- 运行环境在节点对象中,因此this指向本节点对象 -->
复制代码

行内绑定事件的语法是在html节点内,以节点属性的方式绑定,属性名是事件名称前面加'on',属性的值则是一段可执行的 JS 代码段;而属性值最常见的就是一个函数调用;当事件触发时,属性值就会作为JS代码被执行,当前运行环境下没有clickFun函数,因此浏览器就需要跳出当前运行环境,在整个环境中寻找一个叫clickFun的函数并执行这个函数,所以函数内部的this就指向了全局对象window;如果不是一个函数调用,直接在当前节点对象环境下使用this,那么显然this就会指向当前节点对象;动态绑定与事件监听:

<input type="button" value="按钮" id="btn">
<script>
    var btn = document.getElementById('btn');
    btn.onclick = function(){
        this ;  // this指向本节点对象
    }
</script>
复制代码

因为动态绑定的事件本就是为节点对象的属性(事件名称前面加'on')重新赋值为一个匿名函数,因此函数在执行时就是在节点对象的环境下,this自然就指向了本节点对象;

5.window定时器的this
var obj = {
    fun:function(){
        this ;
    }
}
setInterval(obj.fun,1000);      // this指向window对象
setInterval('obj.fun()',1000);  // this指向obj对象
复制代码

setInterval() 是window对象下内置的一个方法,接受两个参数,第一个参数允许是一个函数或者是一段可执行的 JS 代码,第二个参数则是执行前面函数或者代码的时间间隔;

在上面的代码中,setInterval(obj.fun,1000) 的第一个参数是obj对象的fun ,因为 JS 中函数可以被当做值来做引用传递,实际就是将这个函数的地址当做参数传递给了 setInterval 方法,换句话说就是setInterval 的第一参数接受了一个函数,那么此时1000毫秒后,函数的运行就已经是在window对象下了,也就是函数的调用者已经变成了window对象,所以其中的this则指向的全局window对象;

而在 setInterval('obj.fun()',1000) 中的第一个参数,实际则是传入的一段可执行的 JS 代码;1000毫秒后当 JS 引擎来执行这段代码时,则是通过 obj 对象来找到 fun 函数并调用执行,那么函数的运行环境依然在 对象 obj 内,所以函数内部的this也就指向了 obj 对象;

6.apply、call调用

apply方法和call方法都是函数非继承而来的方法,这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的this对象的值。apply() 方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是 Array 的实例,也可以是arguments对象。

call()方法与apply()方法的作用相同,区别是第二个传递给函数的参数必须是一一列举出来。(对于this的指向问题,只要记住一点,this值指向该方法的第一个参数就可以了,语法就这样规定)

var x = 0;
function test() {
&emsp;console.log(this.x);
}

var obj = {};
obj.x = 1;
test.apply(obj,[0])//this指向obj
复制代码
var x = 0;
function test() {
&emsp;console.log(this.x);
}

var obj = {};
obj.x = 1;
test.call(obj,0,1,2)//this指向obj 
复制代码
7.bind调用

这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind() 函数的值。也就是他会返回一个函数。

window.color = "red";
var o = { color: "blue" };
function test(){
alert(this.color);
}
var obj = test.bind(o);//this指向o
obj(); //blue
复制代码

apply、call、bind 的区别

apply、call的作用一样,只是第二个参数传递方式不同,apply要求是数组形式,call要求是将参数一一列举出来, apply和call都是改变this的指向后就执行函数,而bind是改变this指向后返回一个函数,您得手动再执行这个函数

结尾

本文参考阮一峰的this指向文章,以及通读了数篇关于this指向的问题,形成自己的理解,对于有关摘录部分也做了原文链接说明,如有纰漏,欢迎指正。

转载于:https://juejin.im/post/5cb1ef0b6fb9a068646c098f

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值