真正的代码更大,所以我不会发布它。它看起来非常像这样:
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);
// ...
}
问题:基本上,性能; "不要在循环中制作功能"。
在每次迭代中都会创建一堆匿名函数。
我的解决方案:
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;
}
}
}
另一个问题:这些函数中的一些需要访问对象本身的属性,但
this
的范围已经改变。
调用.bind(this)
而不是创建匿名函数值得吗?或几乎相同?
在我的案子中你会做什么?
提前致谢。
答案 0 :(得分:1)
初始化您可以执行的类中的绑定函数
class Test {
fn = (t) => this[t]
}
基本上和你想做的一样。
答案 1 :(得分:1)
问题:基本上,性能; “不要在循环中创建函数”。
你的前提不正确。
JavaScript引擎经过高度优化。每次通过循环或每次调用函数时,它们都不会费力地逐字符地读取源文本,更不用说每次调用回调时。他们扫描,解析和预编译。在最坏的情况下,每个函数调用只会创建一次item => item
之类的函数。更有可能的是,它们将在初始扫描和解析过程中预先创建。
因此,在考虑是否自行预定义功能时,您无需担心性能问题。指导原则应该是程序的可读性和结构。
如果你想预先定义一个函数,只要它不使用this
,考虑在类外定义它:
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);
答案 2 :(得分:1)
虽然在另一个答案中提到
class Test {
// constructor etc.
step = x => x + this.currentStep;
process() {
return this.arr.map(step);
}
}
将是实现预期行为的简洁方法,因为this
已绑定到实例,它需要仍处于第2阶段的公共类字段,因此在没有转换器的许多浏览器中尚不支持
最好记住,您始终可以将this
范围传递给map
和filter
等函数的第二个参数,因此您不必不必事先手动绑定您的函数。然后代码变为
class Test {
// constructor etc.
step(x) { return x + this.currentStep; }
process() {
return this.arr.map(step, this);
}
}
在确保您的功能具有正确的范围时,这非常接近您所考虑的解决方案。
虽然我不太了解浏览器的内部工作原理,但我认为如果代码足够热(经常运行),优化的编译器可能不需要每次运行都重新创建这些匿名函数。