参考mdn和github文章
1. Function.prototype.call()
使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
语法:
fun.call(thisArg, arg1, arg2, ...)
thisArg: 在 fun 函数运行时指定的 this 值,
如果这个函数在非严格模式下运行,则指定为 null 和 undefined 的 this 值会自动指向全局对象(浏览器中就是 window 对象),
同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象
arg1, arg2, ...: 指定的参数列表
示例:
// 使用 call 方法调用父构造函数
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name); // cheese
使用call方法调用匿名函数
var animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (var i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
// call的this指向animals[i]
// 输出:
// #0 Lion: King
// #1 Whale: Fail
如果没有传递第一个参数,this 的值将会被绑定为全局对象
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // sData value is Wisen
在严格模式下,this 的值将会是 undefined
'use strict';
var sData = 'Wisen';
function display() {
console.log('sData value is %s ', this.sData);
}
display.call(); // Cannot read the property of 'sData' of undefined
2. Function.prototype.apply()
作用与call方法一样,区别就是apply()方法接受的是一个参数数组
语法:
func.apply(thisArg, [argsArray])
argsArray: 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数
代码示例:
用 apply 将数组添加到另一个数组
以下代码中,当我们将一个数组 push 进另一个数组时,整个数组被视为一个元素直接 push 进去
var array = ['a', 'b'];
var elements = [1, 2, 3];
array.push(elements);
console.log(array); // ['a', 'b', [1, 2, 3]]
如果我们想要将数组 elemennts 中的元素分别 push 进数组 array 中,可用apply:
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
使用apply和内置函数, 找出数组中最大/小的数字
Math.max(1,2,3,4) // 4
Math.max([1,2,3,4]) // NaN
/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
以下都可正常运行:
Math.max.apply(undefined,[1,2,3,4]) // 4
Math.max.apply(Math,[1,2,3,4]) // 4
3. Function.prototype.bind()
创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用
例子:
var x = 9;
var module = {
x: 81,
getX: function () {
return this.x;
}
};
console.log(module.getX()); // 81
var retrieveX = module.getX;
console.log(retrieveX()); // 9
var boundGetX = retrieveX.bind(module);
console.log(boundGetX()); // 81
call/apply的使用技巧
- 类数组调用数组方法:
// 在数组原型的方法上调用call,执行的this指向arrayLike
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// join语法: arr.join([separator])
// 相当于: arrayLike.join('&')
Array.prototype.join.call(arrayLike, '&'); // name&age&sex
// slice语法:arr.slice([begin[, end]])
Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"]
// slice可以做到类数组转数组
Array.prototype.map.call(arrayLike, function(item){
return item.toUpperCase();
});
// ["NAME", "AGE", "SEX"]
- 类数组转数组
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// 1. slice
Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"]
// 2. splice
Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"]
// 3. ES6 Array.from
Array.from(arrayLike); // ["name", "age", "sex"]
// 4. apply
Array.prototype.concat.apply([], arrayLike)