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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 02:53:24  来源:igfitidea点击:

Typescript: Avoid comparison by reference

javascriptwebreferencecomparisontypescript

提问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 equalsmethod, in typescript that doesn't seem to be possible.

显然打字稿使用引用比较,但在这种情况下没有意义。在 Java 或 C# 中,我会equals在似乎不可能的打字稿中重载该方法。

I considered to loop through the array with foreachand check each entry for equality, but that seems rather complicated and would bloat the code.

我考虑遍历数组foreach并检查每个条目是否相等,但这看起来相当复杂并且会使代码膨胀。

Is there something like equalsin 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 PointListthat only allows Pointobjects to be added via an addmethod, 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 equalsin an equivalent way to what you might have done in C#.

因此,没有一种方法可以equals以与您在 C# 中所做的等效的方式进行覆盖。

However, you would have ended up likely using a Hashor a strongly-typed Dictionaryin 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 Points.

为此,我只是建议您使用关联数组结构来存储Points。

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 Pointdoesn't exist, checking the pointsassociative 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...
});