运行 JavaScript 中数组 update/create 的自定义方法
Run custom method on array update/create in JavaScript
我知道如何向对象添加自定义 属性。
假设我有一个 foo 方法,
const foo = () => { console.log('custom method'); }
我可以将 foo
方法添加到 Array 原型并通过
使用数组变量调用它
Array.prototype.foo = foo;
然后如果我创建一个名为
的数组
bar = [1, 2, 3];
和运行
bar.foo()
它将执行我自定义的 foo 方法。但是我不知道每次创建数组和每次更新数组时如何运行 foo
方法。
我想 运行 自定义方法并在 JavaScript 中的数组 creation/updating 期间存储一些数据。我该怎么做?
假设我有一个自定义方法,
const customMethod = () => {
...doing some stuff
}
每次创建数组并在该数组中存储一些数据时,我希望此自定义方法 运行。就像我想找到数组的最大值并将其存储在带有键 maximum
的数组中,就像我们现在存储 length
一样。这样在 creating/updating 数组之后我就不必计算最大值了。我可以调用 myArray.maximum
并获得最大值。
This approach 做了类似的事情。但是它需要添加事件侦听器和一个新的推送方法,以便它可以在每次使用该自定义推送方法将某些内容推送到数组中时触发一个事件。但在那种情况下,如果我使用常规 Array.prototype.push
方法或使用像这样的展开运算符创建新数组,我的自定义函数将不会更新,newArr = [...oldArray, value]
.
更新: 经过搜索并借助评论中的链接,我发现不扩展数组对象或创建自定义数组类型就无法修改它从头开始(这是不可接受的)。
我尝试扩展现有的 Array 类型并创建 MyCustomArray。但它根本不能用作数组。
class MyCustomArray extends Array {
constructor(...args) {
super(...args);
console.log('custom array');
}
}
知道如何扩展数组以创建我的 CustomArray 类型并向其添加侦听器,这样每次我 create/update CustomArray 时它都会计算最大值并将其设置为数组最大值属性 (代码更改最少)?
所以我的 CustomArray 将像普通数组一样拥有所有方法和实例变量。但它会做一件额外的事情,每次我 update/create 一个 CustomArray 时,它都会计算该数组中的最大值并将其设置为 属性.
我不认为你可以像那样“劫持”所有数组。即使您对本机 Array
函数进行猴子修补,使用文字符号创建的数组,即 []
也不会受其影响:
console.log(new Array(1,2,3));
console.log([4,5,6]);
Array = function () {
throw new Error;
};
try {
console.log(new Array(1,2,3));
} catch (e) {
console.log('Cannot create array with new Array');
}
console.log([4,5,6]);
您可能认为您需要将数组传递给其他对象。您只需要选择适合您的解决方案。我个人会尝试使用代理:
const spy =
(arr, fn) =>
new Proxy(arr, {
get(target, prop) {
if (prop === "max") {
return Math.max(...target);
}
if (prop === "min") {
return Math.min(...target);
}
if (typeof target[prop] === "function") {
fn();
}
return target[prop];
}
});
const arr = spy([1,2,3], () => console.log('spied'));
arr.push(500);
arr.push(-10);
console.log(arr.min, arr.max, JSON.stringify(arr), Array.isArray(arr));
我喜欢代理的一点是它的设计不会妨碍它。在上面的例子中 arr
仍然是一个数组。你可以做你以前做的所有正常的事情。例如 Array.isArray
仍然 returns true
和 JSON.stringify
仍然产生预期的结果。
但是请注意,在上面的实现中,如果您从 arr
生成另一个数组,它不会被自动代理:
const arr = spy([1,2,3], fn);
arr.slice(1); // [2,3] (non-proxied array!)
好吧,它有点蛮力,但是,数组有点像 special,因为如果你 提供扩展 class 的构造函数,其创建新数组的方法将使用该构造函数,因此,例如,myCustomArray.filter
将生成 myCustomArray
对象结果而不是 Array
对象结果。 (如果您不提供构造函数,这将不起作用)。
如果我想随时访问该自定义类型中数组的特定自定义功能,我可能会在创建时将值设为 null,并扩展更改现有对象的方法(如 pop
) 也将它设为 null,然后有一个方法可以提供非空缓存值,或者计算、缓存和 return 当前值。
我没有仔细计算,但我认为只有少数数组方法会更改现有数组(而不是创建新数组),因此应该不需要太多努力。
我知道如何向对象添加自定义 属性。
假设我有一个 foo 方法,
const foo = () => { console.log('custom method'); }
我可以将 foo
方法添加到 Array 原型并通过
Array.prototype.foo = foo;
然后如果我创建一个名为
的数组bar = [1, 2, 3];
和运行
bar.foo()
它将执行我自定义的 foo 方法。但是我不知道每次创建数组和每次更新数组时如何运行 foo
方法。
我想 运行 自定义方法并在 JavaScript 中的数组 creation/updating 期间存储一些数据。我该怎么做?
假设我有一个自定义方法,
const customMethod = () => {
...doing some stuff
}
每次创建数组并在该数组中存储一些数据时,我希望此自定义方法 运行。就像我想找到数组的最大值并将其存储在带有键 maximum
的数组中,就像我们现在存储 length
一样。这样在 creating/updating 数组之后我就不必计算最大值了。我可以调用 myArray.maximum
并获得最大值。
This approach 做了类似的事情。但是它需要添加事件侦听器和一个新的推送方法,以便它可以在每次使用该自定义推送方法将某些内容推送到数组中时触发一个事件。但在那种情况下,如果我使用常规 Array.prototype.push
方法或使用像这样的展开运算符创建新数组,我的自定义函数将不会更新,newArr = [...oldArray, value]
.
更新: 经过搜索并借助评论中的链接,我发现不扩展数组对象或创建自定义数组类型就无法修改它从头开始(这是不可接受的)。
我尝试扩展现有的 Array 类型并创建 MyCustomArray。但它根本不能用作数组。
class MyCustomArray extends Array {
constructor(...args) {
super(...args);
console.log('custom array');
}
}
知道如何扩展数组以创建我的 CustomArray 类型并向其添加侦听器,这样每次我 create/update CustomArray 时它都会计算最大值并将其设置为数组最大值属性 (代码更改最少)?
所以我的 CustomArray 将像普通数组一样拥有所有方法和实例变量。但它会做一件额外的事情,每次我 update/create 一个 CustomArray 时,它都会计算该数组中的最大值并将其设置为 属性.
我不认为你可以像那样“劫持”所有数组。即使您对本机 Array
函数进行猴子修补,使用文字符号创建的数组,即 []
也不会受其影响:
console.log(new Array(1,2,3));
console.log([4,5,6]);
Array = function () {
throw new Error;
};
try {
console.log(new Array(1,2,3));
} catch (e) {
console.log('Cannot create array with new Array');
}
console.log([4,5,6]);
您可能认为您需要将数组传递给其他对象。您只需要选择适合您的解决方案。我个人会尝试使用代理:
const spy =
(arr, fn) =>
new Proxy(arr, {
get(target, prop) {
if (prop === "max") {
return Math.max(...target);
}
if (prop === "min") {
return Math.min(...target);
}
if (typeof target[prop] === "function") {
fn();
}
return target[prop];
}
});
const arr = spy([1,2,3], () => console.log('spied'));
arr.push(500);
arr.push(-10);
console.log(arr.min, arr.max, JSON.stringify(arr), Array.isArray(arr));
我喜欢代理的一点是它的设计不会妨碍它。在上面的例子中 arr
仍然是一个数组。你可以做你以前做的所有正常的事情。例如 Array.isArray
仍然 returns true
和 JSON.stringify
仍然产生预期的结果。
但是请注意,在上面的实现中,如果您从 arr
生成另一个数组,它不会被自动代理:
const arr = spy([1,2,3], fn);
arr.slice(1); // [2,3] (non-proxied array!)
好吧,它有点蛮力,但是,数组有点像 special,因为如果你 提供扩展 class 的构造函数,其创建新数组的方法将使用该构造函数,因此,例如,myCustomArray.filter
将生成 myCustomArray
对象结果而不是 Array
对象结果。 (如果您不提供构造函数,这将不起作用)。
如果我想随时访问该自定义类型中数组的特定自定义功能,我可能会在创建时将值设为 null,并扩展更改现有对象的方法(如 pop
) 也将它设为 null,然后有一个方法可以提供非空缓存值,或者计算、缓存和 return 当前值。
我没有仔细计算,但我认为只有少数数组方法会更改现有数组(而不是创建新数组),因此应该不需要太多努力。