为了挑战自己,我正在用JavaScript实现LINQ(实际上是一组带有类似LINQ功能的函数)。但是,就目前而言,这些函数会立即处理数据;对于某些函数(如Sum或Aggregate),这是正确的行为,但对于其他函数(如Select或While)则是不正确的。
我很好奇是否有一种在JavaScript中可以获得与.Net相同行为的结构,在这种结构下,直到枚举集合或使用具有立即执行功能的函数之前,不会发生任何实际处理。
注:我相信这项任务(在JS中实现LINQ)已经完成。这不是重点。这是一个来自自己的挑战,这可能有助于增加我对LINQ(以及巧合的JS)的理解。除了个人启示外,我很快就要在工作中使用LINQ,根据各个项目的需要 可能会使用JS,并且我在工作之外使用JS进行一些事情。
编辑:看来我吸引了一些不熟悉LINQ的人,所以我想我应该对此进行一些解释。LINQ是.NET中的Language-INtegrated查询。LINQ允许对许多数据源(包括实际的SQL关系数据库)进行类似于SQL的查询,例如LINQ to Objects,这是我试图实现的内容之一。
LINQ的一个特性是对许多方法进行延迟执行。如果我有一个集合`customers`并调用`var query = customers.Where(c => c.Age > 40);`(或在JS中可能会变成`var query = customers.Where(function (c) { return c.Age > 40; });`),返回值是一个接口类型,集合的实际处理(仅返回包含年龄大于40岁的客户的子集)还没有发生。当我使用没有延迟执行的方法时(例如`query.First()`或`query.ToArray()`),那么所有延迟处理都会发生。这可以是链,例如`customers.Where(...).Skip(5).Select(...).OrderBy(...)`(每个“...”都是一个函数)。
简而言之,代码如下:
此外,我目前正在通过在对象和数组上创建原型来实现此项目,迭代
我很好奇是否有一种在JavaScript中可以获得与.Net相同行为的结构,在这种结构下,直到枚举集合或使用具有立即执行功能的函数之前,不会发生任何实际处理。
注:我相信这项任务(在JS中实现LINQ)已经完成。这不是重点。这是一个来自自己的挑战,这可能有助于增加我对LINQ(以及巧合的JS)的理解。除了个人启示外,我很快就要在工作中使用LINQ,根据各个项目的需要 可能会使用JS,并且我在工作之外使用JS进行一些事情。
编辑:看来我吸引了一些不熟悉LINQ的人,所以我想我应该对此进行一些解释。LINQ是.NET中的Language-INtegrated查询。LINQ允许对许多数据源(包括实际的SQL关系数据库)进行类似于SQL的查询,例如LINQ to Objects,这是我试图实现的内容之一。
LINQ的一个特性是对许多方法进行延迟执行。如果我有一个集合`customers`并调用`var query = customers.Where(c => c.Age > 40);`(或在JS中可能会变成`var query = customers.Where(function (c) { return c.Age > 40; });`),返回值是一个接口类型,集合的实际处理(仅返回包含年龄大于40岁的客户的子集)还没有发生。当我使用没有延迟执行的方法时(例如`query.First()`或`query.ToArray()`),那么所有延迟处理都会发生。这可以是链,例如`customers.Where(...).Skip(5).Select(...).OrderBy(...)`(每个“...”都是一个函数)。
简而言之,代码如下:
var collection = [1, 2, 3, 4, 5];
var query = collection.Where(function (n) { return n % 2 == 0; });
collection.push(6);
alert(query.Max());
这将导致结果为“6”。
此外,我目前正在通过在对象和数组上创建原型来实现此项目,迭代
this
的元素,并跳过任何函数元素。类似创建可枚举类可能更好(如果需要返回函数或匿名对象之类的内容,则实际上可能是必需的),但这就是我目前拥有的。我的函数通常显示为以下内容:
Object.prototype.Distinct = Array.prototype.Distinct = function (comparer) {
comparer = comparer || function (a, b) { return a == b; };
var result = [];
for (var idx in this) {
var item = this[idx];
if (typeof item == "function") continue;
if (!result.Contains(item, comparer)) result.push(item);
}
return result;
};
yield
关键字引起的。实际上,这是一种语法糖,编译器将其转换为switch
语句。你应该能够创建一个类似于JavaScript的模拟: http://startbigthinksmall.wordpress.com/2008/06/09/behind-the-scenes-of-the-c-yield-keyword/ - Mister Epicvar query = myCollection.Where(...).Skip(5).Select(...);
(其中“...”是函数)。通过从我的函数返回数组,完全可以实现这一点,因为我的函数是原型化到Array上的,但在.Net中,除非例如我调用了query.First();
,否则_没有_任何处理会发生。 - Brian S