使用循环创建对象链
create object chaining using loop
有没有办法从循环中创建链式对象?
例如输入:
["table1","table2","table3"]
输出:
db
.select(fields)
.from(table)
.innerJoin("table1")
.innerJoin("table2")
.innerJoin("table3")
另一个输入:
["table1","table2","table3","table4","table5"]
输出:
db
.select(fields)
.from(table)
.innerJoin("table1")
.innerJoin("table2")
.innerJoin("table3")
.innerJoin("table4")
.innerJoin("table5")
现在我不知道该怎么做,除了使用 eval,这不是我想做的事。
我需要这个来使用 knex 连接多个表,所以如果有任何其他方法可以这样做,我会很高兴:)
我认为研究函数式编程会对您有所帮助。
我在下方使用了来自互联网 link 的管道函数,但您可以使用 lodash/Ramda/underscore 或任何您喜欢的实用程序库。
我在这里使用的两个主要概念是柯里化和管道。
What is 'Currying'? Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments
we are also making use of curring which is returning a function from another function to compose new functions.
https://medium.com/@venomnert/pipe-function-in-javascript-8a22097a538e A pipe function takes an n sequence of operations; in which each operation takes an argument; process it; and gives the processed output as an input for the next operation in the sequence. The result of a pipe function is a function that is a bundled up version of the sequence of operations.
我们在这里做的是获取一个数组,创建一个新的函数数组,我们要将其应用于一个值。
所以我们想在数据库上执行大量连接。
join => con => con.innerJoin(join);
正在获取一个值,即 "table1" 并返回一个函数,该函数接受一个调用连接的数据库连接,并为下一个连接调用 returns。
const joins = toJoin.map(join => con => con.innerJoin(join));
这创建了传递给管道的函数数组。
const db = ({
select: function (field) {
console.log('select', field)
return db
},
from: function (table) {
console.log('from', table)
return db;
},
innerJoin: function (join) {
console.log('innerJoin', join)
return db;
}
});
const _pipe = (a, b) => (arg) => b(a(arg));
const pipe = (args) => [].slice.apply(args).reduce(_pipe);
function joinInnerMultiple(table, fields, toJoin) {
const joins = toJoin.map(join => con => con.innerJoin(join));
return pipe(joins)(db.select(fields).from(table));
}
joinInnerMultiple("User", "uuid", ["table1", "table2", "table3", "table4", "table5"])
链接的工作方式是,每个方法 return 都是一个对象,下一个方法是 属性。这意味着您可以使用类似 reduce()
的方法来继续调用对象上的下一个方法 return 从前一个。
reduce()
接受一个初始对象,您可以传递该对象以使事情顺利进行。类似于:
var tables = ["table1","table2","table3"]
let res = tables.reduce((res, table) => res.innerJoin(table), db.select(fields).from(table))
为了了解这是如何工作的,我们可以创建一个假的 db
对象,其中包含 return 链中下一个方法的对象的所有方法。 innerJoin
方法只是将参数添加到值 属性:
// fake db object with these methods
const db = {
select(t) {
this.val = [] // initialize val
return this
},
from(t) {
return this
},
innerJoin(name) {
this.val.push("Added: " + name)
return this
}
}
var tables = ["table1","table2","table3"]
// call innerjoin for each of the tables
// this is the same as chaining them
let res = tables.reduce((res, table) => res.innerJoin(table), db.select().from())
// values where accumlated in the val property
console.log(res.val)
有没有办法从循环中创建链式对象? 例如输入:
["table1","table2","table3"]
输出:
db
.select(fields)
.from(table)
.innerJoin("table1")
.innerJoin("table2")
.innerJoin("table3")
另一个输入:
["table1","table2","table3","table4","table5"]
输出:
db
.select(fields)
.from(table)
.innerJoin("table1")
.innerJoin("table2")
.innerJoin("table3")
.innerJoin("table4")
.innerJoin("table5")
现在我不知道该怎么做,除了使用 eval,这不是我想做的事。
我需要这个来使用 knex 连接多个表,所以如果有任何其他方法可以这样做,我会很高兴:)
我认为研究函数式编程会对您有所帮助。
我在下方使用了来自互联网 link 的管道函数,但您可以使用 lodash/Ramda/underscore 或任何您喜欢的实用程序库。
我在这里使用的两个主要概念是柯里化和管道。
What is 'Currying'? Currying is when you break down a function that takes multiple arguments into a series of functions that take part of the arguments we are also making use of curring which is returning a function from another function to compose new functions.
https://medium.com/@venomnert/pipe-function-in-javascript-8a22097a538e A pipe function takes an n sequence of operations; in which each operation takes an argument; process it; and gives the processed output as an input for the next operation in the sequence. The result of a pipe function is a function that is a bundled up version of the sequence of operations.
我们在这里做的是获取一个数组,创建一个新的函数数组,我们要将其应用于一个值。
所以我们想在数据库上执行大量连接。
join => con => con.innerJoin(join);
正在获取一个值,即 "table1" 并返回一个函数,该函数接受一个调用连接的数据库连接,并为下一个连接调用 returns。
const joins = toJoin.map(join => con => con.innerJoin(join));
这创建了传递给管道的函数数组。
const db = ({
select: function (field) {
console.log('select', field)
return db
},
from: function (table) {
console.log('from', table)
return db;
},
innerJoin: function (join) {
console.log('innerJoin', join)
return db;
}
});
const _pipe = (a, b) => (arg) => b(a(arg));
const pipe = (args) => [].slice.apply(args).reduce(_pipe);
function joinInnerMultiple(table, fields, toJoin) {
const joins = toJoin.map(join => con => con.innerJoin(join));
return pipe(joins)(db.select(fields).from(table));
}
joinInnerMultiple("User", "uuid", ["table1", "table2", "table3", "table4", "table5"])
链接的工作方式是,每个方法 return 都是一个对象,下一个方法是 属性。这意味着您可以使用类似 reduce()
的方法来继续调用对象上的下一个方法 return 从前一个。
reduce()
接受一个初始对象,您可以传递该对象以使事情顺利进行。类似于:
var tables = ["table1","table2","table3"]
let res = tables.reduce((res, table) => res.innerJoin(table), db.select(fields).from(table))
为了了解这是如何工作的,我们可以创建一个假的 db
对象,其中包含 return 链中下一个方法的对象的所有方法。 innerJoin
方法只是将参数添加到值 属性:
// fake db object with these methods
const db = {
select(t) {
this.val = [] // initialize val
return this
},
from(t) {
return this
},
innerJoin(name) {
this.val.push("Added: " + name)
return this
}
}
var tables = ["table1","table2","table3"]
// call innerjoin for each of the tables
// this is the same as chaining them
let res = tables.reduce((res, table) => res.innerJoin(table), db.select().from())
// values where accumlated in the val property
console.log(res.val)