js 中四种函数调用模式及 this 指向

128 阅读2分钟

前言

JavaScript 中共有五种调用模式,分别是:函数调用模式、方法调用模式、构造器调用模式、 apply/call 调用模式,本文就来探究一下这几种调用模式的区别及其上下文,也就是 this 指向问题。

函数调用模式

函数调用模式就是调用直接声明函数,其中的 this 在非严格模式下是 Window 对象,在严格模式下是 undefined

function a() {
  console.log(this);
};

a();

image

var fnObj = {
  name: 'objFunction',
  outFn: function () {
    console.log(this);
    let innerFn = function() {
      console.log(this);
    }
    innerFn();
  } 
}

fnObj.outFn();

image

方法调用模式

方法模式就是以函数表达式的方式将函数赋值给一个对象的属性,然后通过对象来调用函数,此时 this 就是调用函数的对象。在这种模式下,只需要记住,是哪个对象调用的, this 就绑定哪个对象

var fnObj = {
  name: 'objFunction',
  outFn: function () {
    console.log(this);
  } 
}

fnObj.outFn();

image

构造器调用模式

我们可以通过 new 关键字调用构造器函数,其中的 this 就会被绑定到新对象上

function CreateObj(name, age) {
  this.name = name;
  this.age = age;
  this.showThis = function () {
    console.log(this);
  }
}

var obj = new CreateObj('knight', '24');
console.log(obj);
obj.showThis()

image

apply/call 调用模式

Apply/call 方法可以我们选择 this 的值,此时 this 就是我们调用 call 方法时的第一个参数,如果我们不指定则为 Window 对象。

apply 方法和 call 方法及 bind 方法的区别:

  1. apply 传给要调用的方法的参数使用数组
  2. call 一个一个传
  3. bind 是返回绑定 this 的对象,我们可以调用这个对象
var obj = {
   name: 'knight',
   age: 23,
};

function aaa(a, b) {
  console.log(this);
  console.log(`${a} : ${b}`);
};

aaa.call(obj, 1, 2);

aaa.apply(obj, [3, 4]);

aaa.bind(obj)(5, 6);

aaa.call();

image

备注

箭头函数没有上下文,即没有 this ,再箭头函数中使用 this 则是使用父作用域的上下文即 this ,若父作用域也没有上下文,就一直向上找

var obj = {
   name: 'knight',
   age: 23,
}

function fun() {
  (() => {
    console.log('箭头函数');
    console.log(this);
  })();
  let a = function() {
    console.log('普通函数');
    console.log(this);
  }();
}

fun.call(obj);

image