首先说下 () 调用、call()调用、apply()调用 三种方式的区别:
区别就是 call 、 apply 可以改变this指向(执行上下文),别的和直接调用没区别

1. 直接调用

function foo(a, b) {
  return a + b;
}

console.log(window.fn(1, 1)) // 2
我们可以把JS中window对象的方法的“window.”省略掉,写成这样:
console.log(fn(1, 1)) // 2

2. 在对象方法里调用

var foo = {
  name: "lokka",
  age: "18",
  message: function() {
    return this.name + this.age;
  }
}

console.log(foo.message()) // lokka18

3. 使用构造函数调用函数

function foo(a, b) {
  this.name = a;
  this.age = b;
}

var client = new foo("lokka", "18");
console.log(client.name + client.age) // lokka18

4. 作为函数方法(call、apply)调用函数

var a = {
  name: "动物园",
}
var b = {
  name: "植物园",
  message: function(a) {
    return this.name + a;
  }
}

console.log(b.message('玫瑰')) // 植物园玫瑰
console.log(b.message.call(a, '熊猫')) // 动物园熊猫
console.log(b.message.apply(a, ['老虎'])) // 动物园老虎