如何在JS中完成方法链接
How can Method Chaining be done in JS?
我想链接这些方法调用:
utils.map([1,2,3,4,5], function (el) { return ++el; } )
和
utils.filter(function (el) {return !el%2; }
它们单独工作正常,但以下内容无法正常工作。如何使以下代码正常工作?
utils
.map([1,2,3,4,5], function (el) { return ++el; })
.filter(function (el) { return !el%2; }
这是我utils
对象:
var utils = {
each: function (collection, iteratee){
return collection.forEach(iteratee);
},
map: function (collection, iteratee) {
return collection.map(iteratee);
},
filter: function (collection, predicate) {
return collection.filter(predicate);
},
find: function (collection, predicate) {
return collection.find(predicate);
}
}
我知道当我链接两个方法时,参数会发生变化,我只需要提供迭代而不是集合。如何做到这一点?
提前谢谢。如果需要,我愿意解释特定概念。
如果你想像这样链接函数,每个函数都需要返回"this"。
请注意,为了使forEach
可链接,您需要添加一个return
语句。就像在 forEach 上的 MDN 文档中一样:
与
map()
或reduce()
不同,它始终返回未定义的值,并且不可链接。典型的用例是在链的末端执行副作用。
其次,像map
和filter
这样的原始方法已经适合链接。正如您在问题末尾已经提到的,您的方法要求第一个参数成为方法的主题,这是一种与链接不兼容的模式。使用链接时,主体必须是公开方法的对象。
您可以通过每次通过链传递新的类似utils
的对象来允许链接。为了创建这些新的utils
实例,将其定义为函数对象更容易,因为这允许您使用 new
关键字创建新的utils
对象。由于它确实是一个构造函数,因此用大写字母编写Utils
是合适的:
function Utils(collection) { // "constructor"
this.collection = collection;
this.each = function(iteratee){
this.collection.forEach.call(this.collection, iteratee);
return this;
},
this.map = function(iteratee){
return new Utils(this.collection.map.call(this.collection, iteratee));
},
this.filter = function(predicate){
return new Utils(this.collection.filter.call(this.collection, predicate));
},
this.find = function(predicate){
return new Utils(this.collection.find.call(collection, predicate));
}
};
// test it
result = new Utils([1,2,3,4,5])
.map(function (el) { return ++el; })
.filter(function (el) { return !(el%2); });
document.write(JSON.stringify(result.collection));
输出:
[2,4,6]
这里Utils
是一个构造函数,并返回一个对象,其中包含作用于私有集合属性的方法。每个方法都返回一个新的Utils
对象,除了在forEach
的情况下,因为它可以只返回当前对象。
所以在这个脚本中,对map
的测试调用实际上是对Utils.map
的调用。
应该说,这并没有给map
、filter
、......可以链接。但我想你还有其他计划来扩展这种模式。
小注意:在表达式!el%2
中,您可能希望首先计算模运算符,然后计算!
,但它在另一个方向上执行。所以我在上面的代码中添加了括号。
这是 trincot 响应的更新版本,采用 ES6 类设计。
class Collection {
constructor(collection) {
if (collection == null || !Array.isArray(collection)) {
throw new Error('collection is null or not an array');
}
this.collection = collection;
}
each(iteratee) {
this.collection.forEach.call(this.collection, iteratee);
return this;
}
map(iteratee) {
return new Collection(this.collection.map.call(this.collection, iteratee));
}
filter(predicate) {
return new Collection(this.collection.filter.call(this.collection, predicate));
}
find(predicate) {
return this.collection.find.call(this.collection, predicate);
}
contains(value) {
return this.collection.includes.call(this.collection, value);
}
get() {
return this.collection;
}
}
const result = new Collection([1, 2, 3, 4, 5])
.map(el => ++el)
.filter(el => !(el % 2))
.get();
console.log(result);
console.log(new Collection([1, 2, 3, 4, 5]).find(e => e === 2));
console.log(new Collection([1, 2, 3, 4, 5]).contains(2));
.as-console-wrapper { top: 0; max-height: 100% !important; }
- 简单的JavaScript方法链接
- D3使用方法链接时的不同行为
- Javascript方法链接定义
- 使用javascript的方法链接不起作用
- 如何在JS中完成方法链接
- 缺点和替代方案 - JS方法链接
- jQuery/JS方法链接
- 是否可以在JavaScript中的变量名后面的新行上开始方法链接
- CoffeeScript调用返回对象的方法(链接)
- 方法链接返回未定义
- 如何在维护命名空间的同时创建类似jQuery的方法链接
- jQuery如何进行方法链接
- 如何有效地调试方法链接函数参数
- JavaScript 方法链接和 this 对象
- NODEJS中的Javascript方法链接
- 带有子方法的方法链接
- 在方法链接中使用函数调用者名称
- 在CouchDB中使用Map-Reduce方法链接文档
- 对象或方法链接如何在jQuery中工作
- 多元素选择器上的jQuery方法链接