javascript:在链中,如何获取先前数组的大小?

时间:2018-11-09 00:06:53

标签: javascript arrays this method-chaining

当链接过滤器并减少时,如何获得过滤后的数组的大小?我需要该尺寸来定制自适应设计CSS。 我的(简化的)代码使用了回调的第3个和第4个参数:

json.articles
.filter(a => keep(a,name))
.reduce((el, a,i,t) =>
    i===0? DOMtag('section',{'class':`media${t.length}`})
        .appendChild(DOMtag(`article`, content(a,0))).parentElement
    : el.appendChild(DOMtag(`article`, content(a,i))).parentElement,
    null);

或更简单(由于luc和下面的懒惰评估建议):

json.articles
.filter(a => keep(a,name))
.reduce((el, a,i,t) =>
    (el || DOMtag('section',{'class':`media${t.length}`}))
        .appendChild(DOMtag(`article`, content(a,i))).parentElement,
    null);

两种代码都可以工作,但是如果有人对以某种方式绑定this有想法,那么可以使用累加器的初始值,例如:

json.articles
.filter(a => keep(a,name))
.reduce((el, a) =>
    el.appendChild(DOMtag(`article`, content(a,i))).parentElement,
    DOMtag('section',{'class':`media${this.length}`}));

有什么主意吗?

1 个答案:

答案 0 :(得分:0)

在传递默认值reduce时,无法访问已过滤的数组长度,因为该表达式是在调用reduce之前求值的。

不过,您可以按以下方式简化函数的内容:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);

  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:
const section = json.articles
  .filter(a => a.name)
  .map(a => DOMTag(`article`, {content: a.name}))
  .reduce((p, c, i, a) =>
    (p || DOMTag('section',{className:`media${a.length}`}))
      .appendChild(c).parentElement
      , null);

section.className = `media${section.childNodes.length}`

// Validation
console.log(section.outerHTML);    

另一个干净的选择是将className设置在链外:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, content) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  return tag;
}

// Start of actual answer code:
const section = json.articles
  .filter(a => a.name)
  .map(el => DOMTag('article', el.name))
  .reduce((p,c) => (p.appendChild(c), p), DOMTag('section'))

section.className = `media${section.childNodes.length}`

// Validation
console.log(section.outerHTML);

选项2:使用函数抽象化容器的创建:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:

function section(children) {
  const section = DOMTag('section', {
    className: `media${children.length}`
  });
  children.forEach(c => section.appendChild(c));
  return section;
}

const s = section(
  json.articles
    .filter(a => a.name)
    .map(el => DOMTag('article', {content: el.name}))
)

// Validation
console.log(s.outerHTML);

选项3:更多功能!如果您绝对必须使用reduce:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:

function defaultSection() {
  let m = false;
  return (a = []) => {
    if (!m) {
      m = DOMTag('section', {className: `media${a.length}`});
    }
    return m;
  };
}

const section = json.articles
  .filter(a => a.name)
  .map(el => DOMTag('article', {content: el.name}))
  .reduce((p,c,i,a) => {
    p(a).appendChild(c);
    return p;
  }, defaultSection())();

// Validation
console.log(section.outerHTML);