ECAMScript 3 给 Function 的原型定义了三个方法,Function.prototype.callFunction.prototype.applyFunction.prototype.bind()

它们的作用一模一样,都能改变 this 的指向并传入参数。区别就是 call() 方法接受的是参数列表,而 apply() 方法接受的是一个参数数组, bind() 方法接受的参数和 call() 一样,但是返回的是一个新函数

使用

  • apply()call() 第一个必选参数指定了函数体内 this 对象的指向

如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象

  1. // 传入 null
  2. var func = function(a, b, c) {
  3. console.log(this); // window
  4. };
  5. func.apply(null);
  6. // 传入 undefined
  7. var func = function(a, b, c) {
  8. console.log(this); // window
  9. };
  10. func.apply(undefined);

如果在严格模式下,传入 null 则为 null,传入 undefined 则为 undefined

  1. // 传入 null
  2. var func = function(a, b, c) {
  3. console.log(this); // null
  4. };
  5. func.apply(null);
  6. // 传入 undefined
  7. var func = function(a, b, c) {
  8. console.log(this); // undefined
  9. };
  10. func.apply(undefined);
  • apply()call() 不同的是第二个可选参数,这个参数将作为参数传给函数

apply() 接受的参数数组或类数组对象

  1. var func = function(a, b, c) {
  2. console.log(a, b, c); // 1 2 3
  3. };
  4. func.apply(null, [1, 2, 3]);

call() 接受的是参数列表

  1. var func = function(a, b, c) {
  2. console.log(a, b, c); // 1 2 3
  3. };
  4. func.call(null, 1, 2, 3);
  • bind()call() 用法一样,但返回一个原函数的拷贝,并拥有指定的 this 值和初始参数
  1. var func = function(a, b, c) {
  2. console.log(a, b, c);
  3. };
  4. var newFunc = func.bind(null, 1, 2, 3);
  5. newFunc(); // 1 2 3

用途

  • 改变 this 的指向
  1. var obj1 = {
  2. name: "sven",
  3. };
  4. var obj2 = {
  5. name: "anne",
  6. };
  7. window.name = "window";
  8. var getName = function() {
  9. console.log(this.name);
  10. };
  11. getName(); // window
  12. getName.call(obj1); // sven
  13. getName.call(obj2); // anne
  • 调用父构造函数,类似继承
  1. function Product(name, price) {
  2. this.name = name;
  3. this.price = price;
  4. }
  5. // category 属性是在各自的构造函数中定义的
  6. function Food(name, price) {
  7. Product.call(this, name, price);
  8. this.category = 'food';
  9. }
  10. function Toy(name, price) {
  11. Product.call(this, name, price);
  12. this.category = 'toy';
  13. }
  14. // 使用 Food 和 Toy 构造函数创建的对象实例都会拥有在 Product 构造函数中添加的 name 属性和 price 属性
  15. var cheese = new Food('feta', 5);
  16. var fun = new Toy('robot', 40);
  • 将数组各项添加到另一个数组
  1. var array = ['a', 'b'];
  2. var elements = [0, 1, 2];
  3. array.push.apply(array, elements);
  4. console.info(array); // ["a", "b", 0, 1, 2]
  • 对于一些需要写循环以便历数组各项的需求,我们可以用 apply() 完成以避免循环
/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];

var max = Math.max.apply(null, numbers); /* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
var min = Math.min.apply(null, numbers);

参考文章