JavaScript 代理:数组排序后聚合通知

JavaScript proxies : aggregate notifications after array sort

提问人:tit 提问时间:7/28/2023 最后编辑:Peter Seligertit 更新时间:8/23/2023 访问量:54

问:

我想找到一种方法,在数组排序后只收到一个通知

有办法吗?谢谢

const callback = function () {
  console.log (...arguments)
}
const array = [2,1]
const handler = {
  set (target, prop, value, receiver) {
    callback (prop, value)
    return Reflect.set (target, prop, value, receiver)
  }
}
const proxy = new Proxy (array, handler)
proxy.sort()
// calls two times callback
// prints "0" 1 and "0" 2
// would like one notification : "array sorted"
JavaScript 数组方法 拦截器 es6-proxy

评论


答:

0赞 InSync 7/28/2023 #1

您可以在其本身上使用 .apply() 陷阱Array#sort()

console.config({ maximize: true });

Array.prototype.sort = new Proxy(Array.prototype.sort, {
  apply(target, thisArg, argumentList) {
    const sortedThis = Reflect.apply(target, thisArg, argumentList);
    console.log('sorted');
    return sortedThis;
  }
});

console.log([2, 1].sort());
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

...或者,如果您希望代理仅影响您的数组,则可以返回一个自定义函数,如果被访问的函数是:property'sort'

console.config({ maximize: true });

const proxy = new Proxy([2, 1], {
  get(target, property, receiver) {
    if (property === 'sort') {
      return function(comparer) {
        const originalSort = Reflect.get(target, property, receiver);
        const sortedThis = originalSort.apply(target, [comparer]);
        
        console.log('sorted');
        
        return sortedThis;
      }
    }
    
    return Reflect.get(target, property, receiver);
  }
});

console.log('.sort() works:', proxy.sort());
console.log('.slice() is fine too:', proxy.slice(1));
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

评论

0赞 tit 7/28/2023
完善。get 实现更适合我的用例。谢谢
0赞 tit 7/28/2023
注意:不会调用''set',这没关系!
1赞 Peter Seliger 8/23/2023 #2

一种不使用代理的可行方法是使用周围方法修饰符的通用实现。后者可以看作是功能包装的一个特殊案例。

这样的修饰符接受两个函数,以及一个 -object 作为其 3 个参数。它确实返回一个函数,该函数将再次返回函数的结果。后者确实在提供的(可选)上下文中被调用,同时也被传递了 -function、它自己的 -reference 和修改后的函数的 -array。proceedhandlertargethandlertargetproceedhandlerarguments

因此,基于这样的修饰符,OP 可以通过修改例如数组实例的 -method 来实现预期的行为,例如这样的 ...sort

const arr = [2, 1];

// reassign the array instance's specifically modified `sort`.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);

...哪里是实现 OP 正在寻找的东西的功能......notifyAboutFinishedTaskhandler

"...数组排序后只有一个通知”

...示例代码 ...

// implementation of `sort`-specific `around`-handler.
function notifyAboutFinishedTask(proceed, handler, args) {
  const arr = this;

  // original task.
  proceed.apply(arr, args);

  // additional notification.
  console.log('\narray sorted');
  console.log('arr ...', arr);
  console.log('arguments ...', args);
}
const arr = [2, 1];

console.log('unsorted arr ...', arr);

// reassign the array instance's specifically modified `sort`.
arr.sort = around(arr.sort, notifyAboutFinishedTask, arr);

// invoking sort twice, once with and once without sort function.
arr.sort();
arr.sort((a, b) => b - a);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>

// implementation of an `around` modifier.
function around(proceed, handler, target) {
  return function (...args) {

    return handler.call(target ?? null, proceed, handler, args);
  };
}

</script>

评论

1赞 tit 8/28/2023
嗨,我还需要让它在代理中工作,该代理也管理访问器。但是,您的答案非常接近,甚至更接近......我喜欢您提供的链接,我尝试在这里总结一下(仅代码):gist.github.com/thipages/085aa96a70231b6c54c0660514bfc858。Thnak 你。
1赞 tit 8/28/2023
是的,我看到了 git 库,感谢您的所有论文/loc/so。要点是,我只是试图有一个更短的代码,可以一目了然地理解,并添加一些我的语义(哎呀!