为了账号安全,请及时绑定邮箱和手机立即绑定

在 JavaScript 中对数组更新/创建运行自定义方法

在 JavaScript 中对数组更新/创建运行自定义方法

幕布斯6054654 2023-07-06 10:19:23
我知道如何向对象添加自定义属性。假设我有一个 foo 方法,const foo = () => { console.log('custom method'); }我可以将该foo方法添加到数组原型并使用数组变量调用它Array.prototype.foo = foo;然后如果我创建一个名为的数组,bar = [1, 2, 3];并运行bar.foo()它将执行我的自定义 foo 方法。但我不知道如何foo在每次创建数组和每次更新数组时运行该方法。我想运行一个自定义方法并在 JavaScript 中创建/更新数组期间存储一些数据。我怎么做?可以说我有一个自定义方法,const customMethod = () => {   ...doing some stuff    }我希望这个自定义方法在每次创建数组时运行并在该数组中存储一些数据。就像我想找到数组的最大值并将其存储在带有键的数组中,maximum就像我们length现在存储的那样。这样在创建/更新数组后我就不必计算最大值。我只要打电话myArray.maximum就能得到最大值。这种方法做了类似的事情。但它需要添加事件侦听器和新的推送方法,以便每次使用该自定义推送方法将某些内容推送到数组时都可以触发事件。Array.prototype.push但在这种情况下,如果我使用常规方法或使用像这样的扩展运算符创建新数组,我的自定义函数将不会更新newArr = [...oldArray, value]。我尝试扩展现有的数组类型并创建 MyCustomArray。但它根本不能作为数组工作。class MyCustomArray extends Array {   constructor(...args) {      super(...args);      console.log('custom array');   }}知道如何扩展数组来创建我的 CustomArray 类型并向其添加侦听器,以便每次创建/更新 CustomArray 时它都会计算最大值并将其设置为数组 max 属性(只需最少的代码更改)?所以我的 CustomArray 将拥有像普通数组一样的所有方法和实例变量。但它会做一件额外的事情,每次我更新/创建 CustomArray 时,它都会计算该数组中的最大值并将其设置为属性。
查看完整描述

3 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

我不认为你可以像这样“劫持”所有数组。即使您对本机Array函数进行猴子修补,使用文字符号 ie 创建的数组也[]不会受到影响:

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仍然返回trueJSON.stringify仍然产生预期结果。

但是请注意,在上面的实现中,如果您从中生成另一个数组,arr则不会自动代理:

const arr = spy([1,2,3], fn);
arr.slice(1); // [2,3] (non-proxied array!)


查看完整回答
反对 回复 2023-07-06
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

你在这里有正确的想法:


class MyCustomArray extends Array {

   constructor(...args) {

      super(...args);

      console.log('custom array');

   }

}

您只需要更改要Array扩展类的类,它应该是Array<T>这样Array的:


class MyCustomArray extends Array<T> {

   constructor(...items) {

      super(...items);

      console.log('custom array');

   }

}

这里的<T>T 代表数组中包含的对象的类型,例如,如果它将是一个仅包含数字的数组,那么您可以将<number>.


现在您可以向该数组添加任何功能并使用以下语法创建该数组的实例:


const array = new MyCustomArray(item1, item2...)

希望这可以帮助


查看完整回答
反对 回复 2023-07-06
?
手掌心

TA贡献1942条经验 获得超3个赞

嗯,它有点暴力,但是,Array 有点特殊,因为如果您为扩展类提供构造函数,则其创建新数组的方法将使用该构造函数,因此,例如,myCustomArray.filter会生成myCustomArray对象结果而不是一个Array对象结果。(如果您不提供构造函数,则这不起作用)。

如果我想随时访问该自定义类型中数组的特定自定义功能,我可能会在创建时将值设置为 null,并扩展更改现有对象(如 )的方法以将其设置为 null,然后将其设置为 null pop。一种方法,该方法可以提供非空缓存值,或者计算、缓存并返回当前值。

我没有仔细计算,但我认为只有少数数组方法可以更改现有数组(而不是创建新数组),因此应该不需要太多努力。


查看完整回答
反对 回复 2023-07-06
  • 3 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信