JavaScript 中特定于类型的扩展方法的等价物是什么?
What's the equivalent of type-specific extension methods in JavaScript?
假设您有 class Person
。它的定义如下:
function Person(name, age) {
this.name = name;
this.age = age;
}
现在假设你有一组 Persons
(或人),你想找到最老的一个。在 C# 中,您可以通过扩展方法执行此操作:
Person Oldest(this IEnumerable<Person> people) =>
people.OrderByDescending(p => p.Age).First();
// Usage:
var elder = people.Oldest();
JavaScript 中的等价物是什么?到目前为止,这就是我所能想到的:
Array.prototype.oldest = function() {
return this.slice().sort(function(left, right) {
return left.age - right.age;
}).pop();
};
这很好用并且语法与 C# 相同,但有一些缺点:
1) 它修改了内置函数的原型,这可能会导致与这样做的其他库发生冲突。
2) 它不是类型安全的:很容易意外调用不包含人的数组,这可能导致运行时错误。
或者,您可以这样定义它:
function oldest(people) {
// ...
}
但是你必须像 oldest(people)
那样调用它而不是 people.oldest()
,这会影响可读性。
在 JavaScript 中是否有任何类型安全的语法 "nice" 方法来执行此操作?
您可以尝试不同的方法:
如果您的程序中只有一个 Person
数组,您可以将方法添加为数组的一个 属性。
var people = [person1, person2];
people.oldest = function() {
// Find the oldest person in this array
};
// ... later
people.oldest();
您可以将方法定义为 Person
的静态 属性,并将 Person
的数组作为参数传递:
Person.oldest = function(people) {
// Find the oldest person in an array
};
var people = [person1, person2];
Person.oldest(people);
扩展Array
(需要ES6)
class People extends Array {
oldest() {
// Find the oldest person in a People collection
}
}
var people = new People();
people.push(person1, person2);
people.oldest();
因为 js 不是类型安全的,你最好将该方法实现为 oldest(people)
...
只需将其视为装饰器模式 - 一种将功能投射到一组未知的相关实体中的合法方法。
然后 - 您可以在您的函数中执行 type-checking。
你可以命名空间它使语法更"obvious"如果这是你的顾虑我猜:
personList(persons).getOldest()
作为一个 objective-c-ish 示例。
然后,您可以将 type-specific 检查添加到 personList 的创建者:
function personList(persons) {
//iterate over persons and make sure
//it's valid. return undefined or {} if not.
return {
getOldest: function() {
// insert clever code here ...
persons.slice().dice().puree();
},
getYoungest: function() {
//even more clever code here ...
}
}
}
通过这种方法,代码
PersonList(cats).getOldest()
抛出一个 'getOldest undefined' 错误——当您有 11,000,000 行 js 代码需要整理时,这可以很容易地发现问题。
它的额外优势是让您的 c# inner-child 感觉更自在(在您的项目文件夹中有一个名为 "ArrayExtensions.Persons.js" 的 js 文件)。感觉像 "chicken soup for the c# soul," 对吧?
另一种带有排序原型的方法。 Person.prototype.ageCompare
检查参数是否是 Person
的实例,如果不是则抛出错误。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.ageCompare = function (b) {
if (!(b instanceof Person)) {
throw 'b is no instance of Person!';
}
return this.age - b.age;
};
var peoples = [new Person('Tim', 31), new Person('Jane', 32), new Person('Frank', 28), new Person('Sue', 31), new Person('Baby', 2)];
peoples.sort(function (a, b) { return a.ageCompare(b); });
document.write('<pre>' + JSON.stringify(peoples, 0, 4) + '</pre>');
假设您有 class Person
。它的定义如下:
function Person(name, age) {
this.name = name;
this.age = age;
}
现在假设你有一组 Persons
(或人),你想找到最老的一个。在 C# 中,您可以通过扩展方法执行此操作:
Person Oldest(this IEnumerable<Person> people) =>
people.OrderByDescending(p => p.Age).First();
// Usage:
var elder = people.Oldest();
JavaScript 中的等价物是什么?到目前为止,这就是我所能想到的:
Array.prototype.oldest = function() {
return this.slice().sort(function(left, right) {
return left.age - right.age;
}).pop();
};
这很好用并且语法与 C# 相同,但有一些缺点:
1) 它修改了内置函数的原型,这可能会导致与这样做的其他库发生冲突。
2) 它不是类型安全的:很容易意外调用不包含人的数组,这可能导致运行时错误。
或者,您可以这样定义它:
function oldest(people) {
// ...
}
但是你必须像 oldest(people)
那样调用它而不是 people.oldest()
,这会影响可读性。
在 JavaScript 中是否有任何类型安全的语法 "nice" 方法来执行此操作?
您可以尝试不同的方法:
如果您的程序中只有一个
Person
数组,您可以将方法添加为数组的一个 属性。var people = [person1, person2]; people.oldest = function() { // Find the oldest person in this array }; // ... later people.oldest();
您可以将方法定义为
Person
的静态 属性,并将Person
的数组作为参数传递:Person.oldest = function(people) { // Find the oldest person in an array }; var people = [person1, person2]; Person.oldest(people);
扩展
Array
(需要ES6)class People extends Array { oldest() { // Find the oldest person in a People collection } } var people = new People(); people.push(person1, person2); people.oldest();
因为 js 不是类型安全的,你最好将该方法实现为 oldest(people)
...
只需将其视为装饰器模式 - 一种将功能投射到一组未知的相关实体中的合法方法。
然后 - 您可以在您的函数中执行 type-checking。
你可以命名空间它使语法更"obvious"如果这是你的顾虑我猜:
personList(persons).getOldest()
作为一个 objective-c-ish 示例。
然后,您可以将 type-specific 检查添加到 personList 的创建者:
function personList(persons) {
//iterate over persons and make sure
//it's valid. return undefined or {} if not.
return {
getOldest: function() {
// insert clever code here ...
persons.slice().dice().puree();
},
getYoungest: function() {
//even more clever code here ...
}
}
}
通过这种方法,代码
PersonList(cats).getOldest()
抛出一个 'getOldest undefined' 错误——当您有 11,000,000 行 js 代码需要整理时,这可以很容易地发现问题。
它的额外优势是让您的 c# inner-child 感觉更自在(在您的项目文件夹中有一个名为 "ArrayExtensions.Persons.js" 的 js 文件)。感觉像 "chicken soup for the c# soul," 对吧?
另一种带有排序原型的方法。 Person.prototype.ageCompare
检查参数是否是 Person
的实例,如果不是则抛出错误。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.ageCompare = function (b) {
if (!(b instanceof Person)) {
throw 'b is no instance of Person!';
}
return this.age - b.age;
};
var peoples = [new Person('Tim', 31), new Person('Jane', 32), new Person('Frank', 28), new Person('Sue', 31), new Person('Baby', 2)];
peoples.sort(function (a, b) { return a.ageCompare(b); });
document.write('<pre>' + JSON.stringify(peoples, 0, 4) + '</pre>');