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

前言

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

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就会指向当前节点对象;动态绑定与事件监听:bash

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

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

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对象;ui

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

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指向的问题,造成本身的理解,对于有关摘录部分也作了原文连接说明,若有纰漏,欢迎指正。

相关文章
相关标签/搜索