ECAMScript 3 给 Function 的原型定义了三个方法,Function.prototype.call、Function.prototype.apply 和 Function.prototype.bind()
它们的作用一模一样,都能改变 this 的指向并传入参数。区别就是 call() 方法接受的是参数列表,而 apply() 方法接受的是一个参数数组, bind() 方法接受的参数和 call() 一样,但是返回的是一个新函数
使用
apply()和call()第一个必选参数指定了函数体内 this 对象的指向
如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象
// 传入 nullvar func = function(a, b, c) {console.log(this); // window};func.apply(null);// 传入 undefinedvar func = function(a, b, c) {console.log(this); // window};func.apply(undefined);
如果在严格模式下,传入 null 则为 null,传入 undefined 则为 undefined
// 传入 nullvar func = function(a, b, c) {console.log(this); // null};func.apply(null);// 传入 undefinedvar func = function(a, b, c) {console.log(this); // undefined};func.apply(undefined);
apply()与call()不同的是第二个可选参数,这个参数将作为参数传给函数
apply() 接受的参数数组或类数组对象
var func = function(a, b, c) {console.log(a, b, c); // 1 2 3};func.apply(null, [1, 2, 3]);
call() 接受的是参数列表
var func = function(a, b, c) {console.log(a, b, c); // 1 2 3};func.call(null, 1, 2, 3);
bind()和call()用法一样,但返回一个原函数的拷贝,并拥有指定的this值和初始参数
var func = function(a, b, c) {console.log(a, b, c);};var newFunc = func.bind(null, 1, 2, 3);newFunc(); // 1 2 3
用途
- 改变 this 的指向
var obj1 = {name: "sven",};var obj2 = {name: "anne",};window.name = "window";var getName = function() {console.log(this.name);};getName(); // windowgetName.call(obj1); // svengetName.call(obj2); // anne
- 调用父构造函数,类似继承
function Product(name, price) {this.name = name;this.price = price;}// category 属性是在各自的构造函数中定义的function Food(name, price) {Product.call(this, name, price);this.category = 'food';}function Toy(name, price) {Product.call(this, name, price);this.category = 'toy';}// 使用 Food 和 Toy 构造函数创建的对象实例都会拥有在 Product 构造函数中添加的 name 属性和 price 属性var cheese = new Food('feta', 5);var fun = new Toy('robot', 40);
- 将数组各项添加到另一个数组
var array = ['a', 'b'];var elements = [0, 1, 2];array.push.apply(array, elements);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);
