Javascript 不通过代理进行所有更改的观察者或代理
Javascript observer or proxy without all changes going through proxy
我正在 Javascript 中写一个数组的子class 以更好地支持矩阵运算(我知道其他存在,这部分是为了让我重新自学线性代数) ,我想要的是在调整矩阵中的任何值时重置一些属性。一些像行列式这样的计算是计算密集型的,我希望能够存储它们以避免重新计算,但是当任何矩阵元素发生变化时它们都需要重置为空。
本质上,我想要的似乎是未直接解决的已弃用 Array.observe(). And the replacement, proxies, seem like a lot of overhead for this one thing. As alluded to in some of the comments on ,我不想只能通过代理访问我的矩阵。到目前为止,我在编写的代码中使用了很多方便的 [i][j]
索引和 [mat[i], mat[j]] = [mat[j], mat[i]]
。
class Matrix extends Array {
constructor() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (Array.isArray(arguments[i])) {
args.push(new Matrix(...arguments[i]));
} else {
args.push(arguments[i]);
}
}
super(...args);
this._determinant = null;
}
determ(forceRecalculate = false) {
if (this._determinant === null || forceRecalculate) {
this.upperEchelon();
}
return this._determinant;
}
upperEchelon(reduced = false) {
//There's a lot of code here but in the process of doing this other thing
//you get 99% of the way to calculating the determinant so it does this
this._determinant = factor;
}
}
基本上,我想要 mat[0][0] = 10
或 mat.push([2,4,5])
之类的东西来更新矩阵中的值以设置 mat._determinant = null
。或者任何等效的方法来标记它需要在下次请求时重新计算。如果有人可以帮助我弄清楚实现方式,我并不反对一定要使用代理,我宁愿让这个 set-to-null-on-update 属性 成为我的 class 功能所固有的。
我真正想要的是一种重载像 []
la C# 这样的基本方法的方法,这样进行更新的函数将在不更改语法的情况下触发它,但我已经辞职了,因为没有它JS.
虽然代理可以工作,但速度也会很慢。一种不同的方法是,对于需要使用 _determinant
值的每个方法,首先通过 different 函数检查是否需要 _determinant
更新(如果是,更新它)。这样,每次数组更改时都不会进行昂贵的重新计算,而只是及时使用结果。例如:
class Matrix extends Array {
constructor() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (Array.isArray(arguments[i])) {
args.push(new Matrix(...arguments[i]));
} else {
args.push(arguments[i]);
}
}
super(...args);
this._determinant = null;
}
// next method is effectively a recursive deep join
// could also use toString if it doesn't interfere with anything else
getString() {
const itemsStr = this.map((item) => (
item instanceof Matrix
? item.getString()
: item
))
.join(',');
const result = '[' + itemsStr + ']';
return result;
}
getDeterm() {
const newString = this.getString();
if (newString !== this._lastString) {
this._lastString = newString;
this.upperEchelon();
}
return this._determinant;
}
upperEchelon() {
console.log('running upperEchelon');
this._determinant = Math.random();
}
}
const m = new Matrix([2, 3, 4], 5);
console.log(m.getDeterm());
// Not calculated again:
console.log(m.getDeterm());
// Mutation, next call of getDeterm will run upperEchelon:
m[0][0] = 1;
console.log(m.getDeterm());
我正在 Javascript 中写一个数组的子class 以更好地支持矩阵运算(我知道其他存在,这部分是为了让我重新自学线性代数) ,我想要的是在调整矩阵中的任何值时重置一些属性。一些像行列式这样的计算是计算密集型的,我希望能够存储它们以避免重新计算,但是当任何矩阵元素发生变化时它们都需要重置为空。
本质上,我想要的似乎是未直接解决的已弃用 Array.observe(). And the replacement, proxies, seem like a lot of overhead for this one thing. As alluded to in some of the comments on [i][j]
索引和 [mat[i], mat[j]] = [mat[j], mat[i]]
。
class Matrix extends Array {
constructor() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (Array.isArray(arguments[i])) {
args.push(new Matrix(...arguments[i]));
} else {
args.push(arguments[i]);
}
}
super(...args);
this._determinant = null;
}
determ(forceRecalculate = false) {
if (this._determinant === null || forceRecalculate) {
this.upperEchelon();
}
return this._determinant;
}
upperEchelon(reduced = false) {
//There's a lot of code here but in the process of doing this other thing
//you get 99% of the way to calculating the determinant so it does this
this._determinant = factor;
}
}
基本上,我想要 mat[0][0] = 10
或 mat.push([2,4,5])
之类的东西来更新矩阵中的值以设置 mat._determinant = null
。或者任何等效的方法来标记它需要在下次请求时重新计算。如果有人可以帮助我弄清楚实现方式,我并不反对一定要使用代理,我宁愿让这个 set-to-null-on-update 属性 成为我的 class 功能所固有的。
我真正想要的是一种重载像 []
la C# 这样的基本方法的方法,这样进行更新的函数将在不更改语法的情况下触发它,但我已经辞职了,因为没有它JS.
虽然代理可以工作,但速度也会很慢。一种不同的方法是,对于需要使用 _determinant
值的每个方法,首先通过 different 函数检查是否需要 _determinant
更新(如果是,更新它)。这样,每次数组更改时都不会进行昂贵的重新计算,而只是及时使用结果。例如:
class Matrix extends Array {
constructor() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (Array.isArray(arguments[i])) {
args.push(new Matrix(...arguments[i]));
} else {
args.push(arguments[i]);
}
}
super(...args);
this._determinant = null;
}
// next method is effectively a recursive deep join
// could also use toString if it doesn't interfere with anything else
getString() {
const itemsStr = this.map((item) => (
item instanceof Matrix
? item.getString()
: item
))
.join(',');
const result = '[' + itemsStr + ']';
return result;
}
getDeterm() {
const newString = this.getString();
if (newString !== this._lastString) {
this._lastString = newString;
this.upperEchelon();
}
return this._determinant;
}
upperEchelon() {
console.log('running upperEchelon');
this._determinant = Math.random();
}
}
const m = new Matrix([2, 3, 4], 5);
console.log(m.getDeterm());
// Not calculated again:
console.log(m.getDeterm());
// Mutation, next call of getDeterm will run upperEchelon:
m[0][0] = 1;
console.log(m.getDeterm());