call,apply,bind和this

282 阅读2分钟

在说call,apply和bind之前先说说this

在ES6之前并没有箭头函数,this是我们很头疼的一件事,我也发现很多老程序员对this的指向判断也不是很准确,由于有了箭头函数,所以在工作中我一般都是用箭头函数,很少使用普通函数,但是在很多面试题中经常有this的一些题目

this

this是动态的,只有在函数调用的时候才能确认下来,和在哪调用的也没有关系。所以我们判断this的指向根据以下两点

1)this是属于哪个函数的

2)这个函数是如何被调用的

简单的说this就是谁调用我我就指向谁,那么根据函数的四种调用模式来判断this的指向

1、函数调用模式(ps:fn();this指向window

var name = "windowsName"
function fn() {
    let name = 'fnName'
    console.log(this.name)
}
fn()

// windowsName

结果是windowsName,为什么呢?因为fn()在全局作用域中,fn()相当于window.fn()所以结果是windowsName,那么我们再做一题

var name = "windowsName"
function fn() {    
    let name = 'fnName'    
    innerFunciton()    
    function innerFunciton() {        
        console.log(this.name)  
    }
}
fn()

// windowsName  

2、方法调用模式(对象名.函数名())

var name = "windowsName"
var a = {    
    name: "fnName",    
    fn : function () {        
        console.log(this.name);  
    }
}
let f = a.fn
f()

// windowsName    

结果很意外是windowsName,为什么呢?我们看一下最后的f()是什么?是函数对象a里面的fn函数,那是谁调用了f(),f()在全局中,所以很显然是windows,所以结果就是windowsName,再看一题

var name = "windowsName"
var a = {    
    name: "fnName",    
    fn : function () {       
        console.log(this.name); 
    }
}
a.fn()

// fnName     

这里就是fnName,我们看是谁调用了fn()? 是对象a,所以this指向a

var name = "windowsName"
function func1() {
      console.log(this.name)
}
var a = {
      name: "Cherry",
      func1: function() {
        console.log(this.name)
      },
      func2: function() { 
        this.func1()
        setTimeout(function () {
          this.func1()
        }, 100);
      }
    }
a.func2()

// Cherry
// windowsName

3、构造函数模式;(new 构造函数();this指向新创建出来的实例)

这里不多做解释

4、上下文模式:方法借用模式call apply bind

任何函数都可以调用这三个方法先说一下call

比如说xiaoming(小明)有一个方法叫liaomei(撩妹),那么xiaowang(小王)并没有这个方法,那怎么办呢?这里就可以用call借用,

xiaoming.liaomei.call(xiaowang,liaomei的参数)

参数:没有参数或者第一个参数为null,函数内的this指向window;一个:指向这个对象,可以改变this;多个:除了第一个其他作为函数的实际参数

apply(和call的方法是一样的,区别在与参数)apply的第二个参数是一个数组

bind创建一个新的函数,并且返回,新函数和fn函数是一模一样的,新函数内的this指向被固定了,固定成了bind的参数,注意点:bind是不会调用fn函数