typescript 打字稿:避免通过引用进行比较
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21406384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typescript: Avoid comparison by reference
提问by lhk
I need to store a list of points and check if a new point is already included in that list
我需要存储一个点列表并检查该列表中是否已包含一个新点
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
window.onload = () => {
var points : Point[] = [];
points.push(new Point(1,1));
var point = new Point(1,1);
alert(points.indexOf(point)); // -1
}
Obviously typescript uses comparison by reference but in this case that doesn't make sense. In Java or C# I would overload the equals
method, in typescript that doesn't seem to be possible.
显然打字稿使用引用比较,但在这种情况下没有意义。在 Java 或 C# 中,我会equals
在似乎不可能的打字稿中重载该方法。
I considered to loop through the array with foreach
and check each entry for equality, but that seems rather complicated and would bloat the code.
我考虑遍历数组foreach
并检查每个条目是否相等,但这看起来相当复杂并且会使代码膨胀。
Is there something like equals
in typescript ? How can I implement my own comparisons ?
equals
打字稿中有类似的东西吗?我怎样才能实现我自己的比较?
回答by danludwig
One thing you can do is try out linq.js. With that, you can do something like this:
您可以做的一件事是尝试linq.js。有了它,你可以做这样的事情:
var foundPoint = Enumerable.From(points)
.SingleOrDefault(function(p) {
return p.x == targetX && p.y == targety;
});
... you could then just implement this function on your object
...然后你可以在你的对象上实现这个功能
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
static equals(points: Point[], candidate: Point): boolean {
var foundPoint = Enumerable.From(points)
.SingleOrDefault((p: Point): boolean => {
return p.x == candidate.x && p.y == candidate.y;
});
return foundPoint != null;
}
}
... and use it like this
...并像这样使用它
var points = createPointsArray();
var point = getSomePoint();
// is point already in array?
var isPointInPoints = Point.equals(points, point)
回答by Fenton
You could wrap the collection in a PointList
that only allows Point
objects to be added via an add
method, which checks to ensure no duplicates are added.
您可以将集合包装在PointList
只允许Point
通过add
方法添加对象的a 中,该方法检查以确保没有添加重复项。
This has the benefit of encapsulating the "No duplicates" rule in a single place, rather than hoping that all calling code will check before adding a duplicate, which would duplicate the rule in many places.
这样做的好处是将“无重复项”规则封装在一个地方,而不是希望所有调用代码在添加重复项之前都进行检查,否则会在许多地方重复规则。
class Point {
constructor(public x: number, public y: number) {
}
}
class PointList {
private points: Point[] = [];
get length() {
return this.points.length;
}
add(point: Point) {
if (this.exists(point)) {
// throw 'Duplicate point';
return false;
}
this.points.push(point);
return true;
}
exists(point: Point) {
return this.findIndex(point) > -1;
}
findIndex(point: Point) {
for (var i = 0; i < this.points.length; i++) {
var existingPoint = this.points[i];
if (existingPoint.x === point.x && existingPoint.y === point.y) {
return i;
}
}
return -1;
}
}
var pointList = new PointList();
var pointA = new Point(1, 1);
var pointB = new Point(1, 1);
var pointC = new Point(1, 2);
pointList.add(pointA);
alert(pointList.length); // 1
pointList.add(pointB);
alert(pointList.length); // 1
pointList.add(pointC);
alert(pointList.length); // 2
回答by WiredPrairie
Typescript doesn't add any functionality to JavaScript. It's just "typed" and some syntax improvements.
Typescript 不会向 JavaScript 添加任何功能。它只是“输入”和一些语法改进。
So, there's not a way to override equals
in an equivalent way to what you might have done in C#.
因此,没有一种方法可以equals
以与您在 C# 中所做的等效的方式进行覆盖。
However, you would have ended up likely using a Hash
or a strongly-typed Dictionary
in C# to do an efficient lookup (in addition to the array potentially), rather than using an "index of" function.
但是,您最终可能会使用C# 中的aHash
或强类型Dictionary
来进行有效的查找(除了可能的数组),而不是使用“索引”函数。
For that, I'd just suggest you use an associative array structure to store the Point
s.
为此,我只是建议您使用关联数组结构来存储Point
s。
You'd do something like:
你会做这样的事情:
class Point {
constructor(public x:Number = 0,
public y:Number = 0 ) {
}
public toIndexString(p:Point):String {
return Point.pointToIndexString(p.x, p.y);
}
static pointToIndexString(x:Number, y:Number):String {
return x.toString() + "@" + y.toString();
}
}
var points:any = {};
var p: Point = new Point(5, 5);
points[p.toIndexString()] = p;
If a Point
doesn't exist, checking the points
associative array will returned undefined
.
如果 aPoint
不存在,则检查points
关联数组将返回undefined
。
A function wrapping the array would be simple:
包装数组的函数很简单:
function findPoint(x:Number, y:Number):Point {
return points[Point.pointToIndexString(x, y)];
}
Looping through all points would be easy to:
循环遍历所有点很容易:
// define the callback (similar in concept to defining delegate in C#)
interface PointCallback {
(p:Point):void;
}
function allPoints(callback:PointCallback):void {
for(var k in points) {
callback(points[k]);
}
}
allPoints((p) => {
// do something with a Point...
});