最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Proxy "Array.prototype.push" - Stack Overflow

programmeradmin5浏览0评论

I was looking around online and I saw someone do something similar, Array.prototype.push was proxied and every push was handled, I want to do something like this:

new Proxy(Array.prototype.push, handler);

const array = [];

array.push("e"); // logs "e" to the console somehow from the handler

How can this be achieved?

I was looking around online and I saw someone do something similar, Array.prototype.push was proxied and every push was handled, I want to do something like this:

new Proxy(Array.prototype.push, handler);

const array = [];

array.push("e"); // logs "e" to the console somehow from the handler

How can this be achieved?

Share Improve this question edited Mar 1, 2023 at 14:50 Sebastian Kaczmarek 8,5154 gold badges24 silver badges43 bronze badges asked Mar 1, 2023 at 14:49 breadbread 1902 silver badges11 bronze badges 6
  • 1 Are you sure you need to use a proxy?, are you wanting everywhere you you create an array and call push you get logged, if so you just override the prototype, ps. Be careful doing this though, altering prototypes is a little bit frowned on. – Keith Commented Mar 1, 2023 at 14:56
  • 1 This sounds like an XY problem. What do you want to achieve which requires proxying a built-in method? – VLAZ Commented Mar 1, 2023 at 14:56
  • @VLAZ I'm making a script that needs to be injected into a website, I'm trying to access an object that has certain attributes, I'm trying to proxy Array.push so I can do checks on each push and see if the push was done on the object I'm looking for, and if it was, save the object. – bread Commented Mar 1, 2023 at 14:58
  • 1 You can't use a proxy to intercept existing arrays, proxies work by wrapping an existing object and then all access is done via the proxy. Like I mentioned in first ment you can override the array protototype, but be very very careful when doing this. – Keith Commented Mar 1, 2023 at 15:00
  • 1 @Keith is right. The only way to somehow get things to work as described is to overwrite the built-in global array. Which is usually to be avoided. Even if you were to modify it, at that point it wouldn't matter whether you used a proxy or not as you're already intrusively changing the built-in global. Proxies are transparent only when you get a chance to hand over a proxy instead of the object. Then it's the same to the consumer. But making sure all consumers use a proxy of an object you don't control is not that. And when built-ins are involved you best thread carefully. – VLAZ Commented Mar 1, 2023 at 15:05
 |  Show 1 more ment

4 Answers 4

Reset to default 5

This will work:

const handler = {
  apply(target, thisArg, argumentsList) {
    console.log(`called push with argument:', ${argumentsList}`);
    return Reflect.apply(target, thisArg, argumentsList)
  }
};

Array.prototype.push = new Proxy(Array.prototype.push, handler);


const a = []

a.push(1)

More info:

MDN article about Proxy

handler.apply

But it can break things so be careful

You need to proxy the array and call methods from the proxy.

// Based on:
// - https://stackoverflow./a/35610685/1762224
// - https://stackoverflow./a/47911346/1762224
const
  arr = [],
  traceMethods = ['push', 'unshift'],
  proxiedArr = new Proxy(arr, {
    get(target, prop, receiver) {
      if (traceMethods.includes(prop)) {
        return function(item) {
          console.log(`${prop}ing ${item}`);
          return target[prop](...arguments);
        }
      }
      return target[prop];
    },
  });

proxiedArr.push('e'); // logs 'pushing e' to the console
proxiedArr.unshift('f'); // logs 'unshifting f' to the console

console.log(arr); // ["f", "e"]
.as-console-wrapper { top: 0; max-height: 100% !important; }

Capturing push method on all arrays on a webpage can easily be done by overriding the prototype method.

But, a big warning, doing this could potentially cause side effect. In fact a long time ago in Javascript land they used to be a lib called prototype that actually did this, and got a lot of flack for doing it.

Saying that, there is one area were overriding built-in is remended, and that's pollyfilling new ES features.

If all your wanting to do is log into the console, maybe for debugging purposes, then your maybe OK.

So with all the warnings out the way, here is an example.

//keep a reference to the old push method
const oldPush = Array.prototype.push;
//now implement our replacement.
Array.prototype.push = function (...args) {
  console.log(...args);
  return oldPush.call(this, ...args);
}

//lets test.
const a = []
a.push(1)
a.push(1,2,3);
a.push('hello','there');

Of course, you could also do this without the Proxy for a solution that doesn't change how Arrays work for the rest of the code (which can produce the kind of issue that is hard to troubleshoot):

function push (arr, ...args) {
  console.log('Pushed called with', ...args)
  arr.push(...args)
}

const arr = []

push(arr, 1)
console.log('arr', arr)

发布评论

评论列表(0)

  1. 暂无评论