如何在无限循环中重用数组函数
How to reuse array functions in an infinite loop
真正的代码比较大,就不post了。它看起来很像这样:
class A {
process(source) {
// I perform several operations with array helper functions here:
const filtered = source.filter(item => item);
const condition = filtered.some(item => item);
if (condition) {
const mapped = source.map(item => /* Mapping operations... */);
const sorted = mapped.sort((a, b) => { /* Some sort conditions... */ });
return sorted;
} else {
const mapped2 = filtered.map(item => /* A different mapping operation... */);
return mapped2;
}
}
}
const a = new A();
while (true) {
const source = getSourceFromSomewhere(); // Array (40 - 50 items aprox)
const b = a.process(source);
// ...
}
The problem: Basically, performance; "Don't make functions within a loop".
每次迭代都会创建一堆匿名函数。
我的解决方案:
class A {
// Predefine it:
sort() { /* Sort logic */ }
map() { /* Map logic */ }
map2() { /* Map logic */ }
filter() { /* Filter logic */ }
some() { /* Condition */ }
process(source) {
const filtered = source.filter(this.filter); // Note: Scope of 'this' is changed.
const condition = filtered.some(this.some);
if (condition) {
const mapped = source.map(this.map);
const sorted = mapped.sort(this.sort);
return sorted;
} else {
const mapped2 = filtered.map(this.map2);
return mapped2;
}
}
}
Another problem: Some of this functions need access to properties of the object itself, but the scope of this
has been changed.
值得调用 .bind(this)
而不是创建匿名函数吗?还是差不多?
如果是我,你会怎么做?
提前致谢。
要在 class 中初始化绑定函数,您可以这样做
class Test {
fn = (t) => this[t]
}
基本上和你想做的一样。
The problem: Basically, performance; "Don't make functions within a loop".
你的前提不正确。
JavaScript 引擎经过高度优化。他们不会在每次循环或每次调用函数时都费力地逐个字符地阅读源文本,更不用说每次调用回调了。他们扫描、解析和预编译。在最坏的情况下,像 item => item
这样的函数在每次函数调用时只会创建一次。更有可能的是,它们将在初始扫描和解析过程中预先创建。
因此,您在考虑是否自行预定义函数时无需担心性能问题。指导原则应该是程序的可读性和结构。
如果你确实想预定义一个函数,只要它不使用 this
,考虑在 class:
之外定义它
function filterFunc(item) { return item.val < MAX; }
class A {
process() {
const filtered = source.filter(filterFunc);
如果你确实需要“this”,那么在现代 JS 中最好写成
class A {
filterFunc(item) { return item.val < this.MAX; }
process() {
const filtered = source.filter(item => this.filterFunc(item));
而不是担心绑定 this.filterFunc
让你写
class A {
constructor () { this.filterFunc = this.filterFunc.bind(this); }
process() {
const filtered = source.filter(this.filterFunc);
虽然在另一个答案中提到
class Test {
// constructor etc.
step = x => x + this.currentStep;
process() {
return this.arr.map(step);
}
}
将是实现预期行为的简洁方法,因为 this
已经绑定到实例,它需要 public class 字段,该字段仍处于第 2 阶段,并且因此在没有 t运行spiler.
的许多浏览器中尚不支持
最好记住,您始终可以 将 this
作用域传递给 map
和 filter
[=27= 等函数的第二个参数],所以你不必事先手动绑定你的函数。然后代码变成
class Test {
// constructor etc.
step(x) { return x + this.currentStep; }
process() {
return this.arr.map(step, this);
}
}
这与您在确保您的函数具有正确范围的同时想到的解决方案非常接近。
虽然我不太了解浏览器的内部工作原理,但我认为如果代码足够热(经常 运行),优化的编译器可能不需要在每个 运行.
真正的代码比较大,就不post了。它看起来很像这样:
class A {
process(source) {
// I perform several operations with array helper functions here:
const filtered = source.filter(item => item);
const condition = filtered.some(item => item);
if (condition) {
const mapped = source.map(item => /* Mapping operations... */);
const sorted = mapped.sort((a, b) => { /* Some sort conditions... */ });
return sorted;
} else {
const mapped2 = filtered.map(item => /* A different mapping operation... */);
return mapped2;
}
}
}
const a = new A();
while (true) {
const source = getSourceFromSomewhere(); // Array (40 - 50 items aprox)
const b = a.process(source);
// ...
}
The problem: Basically, performance; "Don't make functions within a loop".
每次迭代都会创建一堆匿名函数。
我的解决方案:
class A {
// Predefine it:
sort() { /* Sort logic */ }
map() { /* Map logic */ }
map2() { /* Map logic */ }
filter() { /* Filter logic */ }
some() { /* Condition */ }
process(source) {
const filtered = source.filter(this.filter); // Note: Scope of 'this' is changed.
const condition = filtered.some(this.some);
if (condition) {
const mapped = source.map(this.map);
const sorted = mapped.sort(this.sort);
return sorted;
} else {
const mapped2 = filtered.map(this.map2);
return mapped2;
}
}
}
Another problem: Some of this functions need access to properties of the object itself, but the scope of
this
has been changed.
值得调用 .bind(this)
而不是创建匿名函数吗?还是差不多?
如果是我,你会怎么做?
提前致谢。
要在 class 中初始化绑定函数,您可以这样做
class Test {
fn = (t) => this[t]
}
基本上和你想做的一样。
The problem: Basically, performance; "Don't make functions within a loop".
你的前提不正确。
JavaScript 引擎经过高度优化。他们不会在每次循环或每次调用函数时都费力地逐个字符地阅读源文本,更不用说每次调用回调了。他们扫描、解析和预编译。在最坏的情况下,像 item => item
这样的函数在每次函数调用时只会创建一次。更有可能的是,它们将在初始扫描和解析过程中预先创建。
因此,您在考虑是否自行预定义函数时无需担心性能问题。指导原则应该是程序的可读性和结构。
如果你确实想预定义一个函数,只要它不使用 this
,考虑在 class:
function filterFunc(item) { return item.val < MAX; }
class A {
process() {
const filtered = source.filter(filterFunc);
如果你确实需要“this”,那么在现代 JS 中最好写成
class A {
filterFunc(item) { return item.val < this.MAX; }
process() {
const filtered = source.filter(item => this.filterFunc(item));
而不是担心绑定 this.filterFunc
让你写
class A {
constructor () { this.filterFunc = this.filterFunc.bind(this); }
process() {
const filtered = source.filter(this.filterFunc);
虽然在另一个答案中提到
class Test {
// constructor etc.
step = x => x + this.currentStep;
process() {
return this.arr.map(step);
}
}
将是实现预期行为的简洁方法,因为 this
已经绑定到实例,它需要 public class 字段,该字段仍处于第 2 阶段,并且因此在没有 t运行spiler.
最好记住,您始终可以 将 this
作用域传递给 map
和 filter
[=27= 等函数的第二个参数],所以你不必事先手动绑定你的函数。然后代码变成
class Test {
// constructor etc.
step(x) { return x + this.currentStep; }
process() {
return this.arr.map(step, this);
}
}
这与您在确保您的函数具有正确范围的同时想到的解决方案非常接近。
虽然我不太了解浏览器的内部工作原理,但我认为如果代码足够热(经常 运行),优化的编译器可能不需要在每个 运行.