概念
Function.prototype.apply(thisArg [, argsArray])
apply() 方法调用时,改变函数内部 this 指向,传入一个数组或一个类数组对象的形式提供的参数,函数会把数组进行解构传递。
-
thisArg- 在
func函数运行时使用的this值。 - 请注意,
this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,null或undefined自动替换为指向全局对象,原始值会被包装 - 当第一个参数为
null或undefined时,可以使用数组展开语法实现类似的结果
- 在
-
argsArray可选一个数组或者类数组对象,其中的数组元素将作为单独的参数传给
func函数。如果该参数的值为null或undefined,则表示不需要传入任何参数。
使用示例
用 apply 将数组各项添加到另一个数组
const array = ["a", "b"];
const elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
使用 apply 和内置函数
- 对于一些需要写循环以遍历数组各项的需求,我们可以用
apply完成以避免循环
// 找出数组中最大/小的数字
const numbers = [5, 6, 2, 3, 7];
// 使用 Math.min/Math.max 以及 apply 函数时的代码
let max = Math.max.apply(null, numbers); // 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..)
let min = Math.min.apply(null, numbers);
- 数组切块
function minOfArray(arr) {
let min = Infinity;
let QUANTUM = 32768;
for (let i = 0, len = arr.length; i < len; i += QUANTUM) {
const submin = Math.min.apply(
null,
arr.slice(i, Math.min(i + QUANTUM, len)),
);
min = Math.min(submin, min);
}
return min;
}
使用 apply 来链接构造器
构造器中使用一个类数组对象而非参数列表
Function.prototype.construct = function (aArgs) {
let oNew = Object.create(this.prototype);
this.apply(oNew, aArgs);
return oNew;
};
function MyConstructor() {
for (let nProp = 0; nProp < arguments.length; nProp++) {
this["property" + nProp] = arguments[nProp];
}
}
let myArray = [4, "Hello world!", false];
let myInstance = MyConstructor.construct(myArray);
console.log(myInstance.property1); // logs 'Hello world!'
console.log(myInstance instanceof MyConstructor); // logs 'true'
console.log(myInstance.constructor); // logs 'MyConstructor'
模拟
Function.prototype.newApply = function (context, parameter) {
if (typeof this !== "function") {
console.error("type error");
}
if (typeof context === "object") {
context = context || window;
} else {
context = Object.create(null);
}
if (!(parameter instanceof Array)) {
parameter = [];
}
context.fn = this;
var args = [],
result = null;
for (var i = 0, len = parameter.length; i < len; i++) {
args.push("parameter[" + i + "]");
}
result = eval("context.fn(" + args + ")");
delete context.fn;
return result;
};
Function.prototype.newApply = function (context, parameter) {
if (typeof this !== "function") {
console.error("type error");
}
if (typeof context === "object") {
context = context || window;
} else {
context = Object.create(null);
}
if (!Array.isArray(parameter)) {
parameter = [];
}
let fn = Symbol();
let result = null;
context[fn] = this;
result = context[fn](...parameter);
delete context[fn];
return result;
};