问题描述
我有一个标记的模板文字片段生成器,看起来像这样:
function fragment(chunks,...args) {
return new Fragment(chunks,args);
};
class Fragment {
constructor(chunks,args) {
this.chunks = chunks;
this.args = args;
}
}
想法是能够将标记的模板文字拆分为不同的部分,并具有merge
函数,该函数将任意深度嵌套的片段树转换为chunks
数组和args
数组就好像它只是一个以标签开头的大模板文字:
function f() {}
function g() {}
const part = fragment`A ${f} B`
const nested = fragment`C ${part} D ${g} E ${part}`
const [chunks,args] = merge(nested)
console.log(chunks) // ["C A "," B D "," E A "," B"]
console.log(args) // [function f,function g,function f]
实现merge
的最好,最有效的算法是什么?谢谢。
解决方法
由于模板文字有两个parallel arrays,所以有点难看,但这是我要做的:
function mergeInto(target,acc,{chunks: srcChunks,args: srcArgs}) {
const {chunks: targetChunks,args: targetArgs} = target;
for (var i=0; i<srcArgs.length; i++) {
acc += srcChunks[i];
if (srcArgs[i] instanceof Fragment) {
acc = mergeInto(target,srcArgs[i]);
} else {
targetChunks.push(acc);
targetArgs.push(srcArgs[i]);
acc = "";
}
}
return acc + srcChunks[i];
}
function merge(fragment) {
const chunks = [],args = [];
chunks.push(mergeInto({chunks,args},"",fragment));
return [chunks,args];
}
,
这是另一种解释,尽管在没有看到更多数据样本的情况下对其执行没有完全信心。简而言之,如果在merge
函数中处理chunks
和args
的管理,则不需要fragment
函数...
function fragment(chunks,...args) {
let chunksCopy = [];
let argsCopy = [];
for ( i = 0; i < args.length; i++ ) {
if ( args[ i ] instanceof Fragment ) {
chunksCopy[ i ] = chunks[ i ] + args[ i ].chunks[ 0 ];
chunksCopy[ i + 1 ] = args[ i ].chunks[ 1 ] + chunks[ i + 1 ];
//argsCopy.splice( i,args[ i ].args[ 0 ] );
argsCopy[ i ] = args[ i ].args[ 0 ];
} else {
if ( chunksCopy[ i ] == null ) {
chunksCopy[ i ] = chunks[ i ];
}
argsCopy[ i ] = args[ i ];
}
}
if ( chunksCopy[ i ] == null ) {
chunksCopy[ i ] = chunks[ i ];
}
return new Fragment( chunksCopy,argsCopy );
};
class Fragment {
constructor( chunks,args ) {
this.chunks = chunks;
this.args = args;
}
}
function f() {}
function g() {}
const part = fragment`A ${f} B`;
console.log( part );
const nested = fragment`C ${part} D ${g} E ${part}`;
console.log( nested )
console.log( nested.chunks ); // ["C A "," B D "," E A "," B"]
console.log( nested.args ) // [function f,function g,function f]
请注意,在使用“运行代码段”时,console.log( nested.args )
似乎显示了第三个函数自变量作为对f()
的第一个函数自变量的引用。为了更清楚地解释结果,请在浏览器调试模式下复制并运行以上内容...