お題:カッコいい方法と、最速の方法で実装しなさい。

これを一番カッコいい(笑)方法と、一番速そうな方法で実装して下さい。

function getParent(node)
node の親のリスト。どうせひとつですけどね。

function getAncestor(node)
node の祖先のリスト。逆文書順。

function getChild(node)
node の子のリスト。文書順。

function getDescendant(node)
node の子孫のリスト。文書順。

function getFollowingSibling(node)
node の弟のリスト。文書順。

function getFollowing(node)
node よりも文書順で後ろにあるノードのリスト(ただし子孫を除く)。文書順。

function getPrecedingSibling(node)
node の兄のリスト。逆文書順。

function getPreceding(node)
node よりも文書順で前にあるノードのリスト(ただし先祖を除く)。逆文書順。

まずは、基本から。body 以下で、テキストノードは必要なかったのですね。;_;

<!DOCTYPE html>
<title></title>

<div id="A" style="display:none">
  <div id="B">
    <div id="C">A/B/C</div>
    <div id="D">A/B/D</div>
    <div id="E">A/B/E</div>
  </div>
  <div id="F">
    <div id="G">A/F/G</div>
    <div id="H">A/F/H</div>
    <div id="I">
      <div id="J">A/F/I/J</div>
      <div id="K">
        <div id="L">A/F/I/K/L</div>
        <div id="M">A/F/I/K/M</div>
        <div id="N">A/F/I/K/N</div>
      </div>
      <div id="O">A/F/I/O</div>
    </div>
    <div id="P">A/F/P</div>
    <div id="Q">A/F/P</div>
  </div>
  <div id="R">
    <div id="S">A/R/S</div>
    <div id="T">A/R/T</div>
    <div id="U">A/R/U</div>
  </div>
</div>

<pre>
目安(要素のみ)
#I の parent[F]
#I の ancestor → [F, A]
#I の child → [J, K, O]
#I の descendant → [J, K, L, M, N, O]
#I の following-sibling → [P, Q]
#I の following → [P, Q, R, S, T, U]
#I の preceding-sibling → [H, G]
#I の preceding → [H, G, E, D, C, B]
</pre>
<script type="application/javascript; version=1.8">

// 親のリスト
function getParent (node) {
  if ((! node) || (node.ownerDocument.body === node))
    return [];
  else
    return [node.parentNode];
}


// node の祖先のリスト(逆文書順)
function getAncestor (node) {
  var result = [];
  var root;
  
  if (node) {
    root = node.ownerDocument.body;
    while (node = node.parentNode)
      if (root != node)
        result[result.length] = node;
      else
        break;
  }

  return result;
}


// node の子のリスト(文書順)
function getChild (node) {
  var result = [];
  var n;
  
  if (node) {
    n = node.firstChild;
    do {
      if (1 === n.nodeType)
        result[result.length] = n;
    } while (n = n.nextSibling);
  }
  
  return result;
}


// node の子孫のリスト(文書順)
function getDescendant (node) {
  var result = [];
  var root = node;
  var n;

  while (node) {
    if (! (n = node.firstChild))
      while (! (n = node.nextSibling))
        if (root === (node = node.parentNode))
          return result;

    if (1 === n.nodeType)
      result[result.length] = n;
    node = n;
  }
}


// node の弟のリスト(文書順)
function getFollowingSibling (node) {
  var result = [];
  
  while (node = node.nextSibling)
    if (1 === node.nodeType)
      result[result.length] = node;

  return result;
}


// node よりも文書順で後ろにあるノードのリスト(ただし子孫を除く)(文書順)
function getFollowing (node) {
  if (! node)
    return [];

  var result = [];
  var root = node.ownerDocument.body;
  var n;

  while (! (n = node.nextSibling))
    if (root === (node = node.parentNode))
      return result;
  
  while (node = n) {
    if (! (n = node.firstChild))
      while (! (n = node.nextSibling))
        if (root === (node = node.parentNode))
          return result;

    if (1 === n.nodeType)
      result[result.length] = n;
  }
}



// node の兄のリスト(逆文書順)
function getPrecedingSibling (node) {
  var result = [];
  
  while (node = node.previousSibling)
    if (1 === node.nodeType)
      result[result.length] = node;

  return result;
}


// node よりも文書順で前にあるノードのリスト(ただし先祖を除く)(逆文書順)
function getPreceding (node) {
  if (! node)
    return result;

  var result = [];
  var root = node.ownerDocument.body;
  var pass = node.parentNode;
  var n;

  while (true) {
    if (n = node.previousSibling) {
      while (n.hasChildNodes())
        n = n.lastChild;
      node = n;
    }
    else {
      node = node.parentNode;
      if (root === node)
        return result;

      if (pass === node) {
        pass = pass.parentNode;
        continue;
      }
    }
    
    if (1 === node.nodeType)
      result[result.length] = node;
  }
}


function getId (ary) {
  return ary.map (function (n) n.id || n.nodeName)
}

var target = document.querySelector ('#I');
alert (getId (getParent (target)));
alert (getId (getAncestor (target)));
alert (getId (getChild (target)));
alert (getId (getDescendant (target)));
alert (getId (getFollowingSibling (target)));
alert (getId (getFollowing (target)));
alert (getId (getPrecedingSibling (target)));
alert (getId (getPreceding (target)));
</script>

あ〜・・・。その2、テキストノードとルートの縛りを外す。

<!DOCTYPE html>
<title></title>

<div id="A" style="display:none">
  <div id="B">
    <div id="C">A/B/C</div>
    <div id="D">A/B/D</div>
    <div id="E">A/B/E</div>
  </div>
  <div id="F">
    <div id="G">A/F/G</div>
    <div id="H">A/F/H</div>
    <div id="I">
      <div id="J">A/F/I/J</div>
      <div id="K">
        <div id="L">A/F/I/K/L</div>
        <div id="M">A/F/I/K/M</div>
        <div id="N">A/F/I/K/N</div>
      </div>
      <div id="O">A/F/I/O</div>
    </div>
    <div id="P">A/F/P</div>
    <div id="Q">A/F/P</div>
  </div>
  <div id="R">
    <div id="S">A/R/S</div>
    <div id="T">A/R/T</div>
    <div id="U">A/R/U</div>
  </div>
</div>

<pre>
目安(要素のみ)
#I の parent[F]
#I の ancestor → [F, A]
#I の child → [J, K, O]
#I の descendant → [J, K, L, M, N, O]
#I の following-sibling → [P, Q]
#I の following → [P, Q, R, S, T, U]
#I の preceding-sibling → [H, G]
#I の preceding → [H, G, E, D, C, B]
</pre>
<script type="application/javascript; version=1.8">

// 親のリスト
function getParent (node) {
  if (node)
    return [node.parentNode];
  else
    return [];
}


// node の祖先のリスト(逆文書順)
function getAncestor (node) {
  var result = [];
  
  if (node) {
    while (node = node.parentNode)
      result[result.length] = node;
  }

  return result;
}


// node の子のリスト(文書順)
function getChild (node) {
  if (node) {
    if (node.hasChildNodes ())
      return Array.slice (node.childNodes);
  }
  return [];
}


// node の子孫のリスト(文書順)
function getDescendant (node) {
  var result = [];
  var root = node;
  var n;

  while (node) {
    if (! (n = node.firstChild))
      while (! (n = node.nextSibling))
        if (root === (node = node.parentNode))
          return result;

    result[result.length] = node = n;
  }
  return result;
}

// node の弟のリスト(文書順)
function getFollowingSibling (node) {
  var result = [];
  
  while (node = node.nextSibling)
    result[result.length] = node;

  return result;
}


// node よりも文書順で後ろにあるノードのリスト(ただし子孫を除く)(文書順)
function getFollowing (node) {
  if (! node)
    return [];

  var result = [];
  var root = node.ownerDocument.body;
  var n;

  while (! (n = node.nextSibling))
    if (! (node = node.parentNode))
      return result;
  
  while (node = n) {
    if (! (n = node.firstChild))
      while (! (n = node.nextSibling))
        if (! (node = node.parentNode))
          return result;

    result[result.length] = n;
  }
  return result;
}


// node の兄のリスト(逆文書順)
function getPrecedingSibling (node) {
  var result = [];
  
  while (node = node.previousSibling)
    result[result.length] = node;

  return result;
}


// node よりも文書順で前にあるノードのリスト(ただし先祖を除く)(逆文書順)
function getPreceding (node) {
  if (! node)
    return result;

  var result = [];
  var pass = node.parentNode;
  var n;

  while (true) {
    if (n = node.previousSibling) {
      while (n.hasChildNodes())
        n = n.lastChild;
      node = n;
    }
    else {
      node = node.parentNode;
      if (! node)
        return result;

      if (pass === node) {
        pass = pass.parentNode;
        continue;
      }
    }
    
    result[result.length] = node;
  }
}


function getId (ary) {
  return ary.map (function (n) n.id || n.nodeName).join(",\n");
}

var target = document.querySelector ('#I');
alert ("getParent: \n"           + getId (getParent (target)));
alert ("getAncestor:  \n"         + getId (getAncestor (target)));
alert ("getChild:  \n"            + getId (getChild (target)));
alert ("getDescendant:  \n"       + getId (getDescendant (target)));
alert ("getFollowingSibling:  \n" + getId (getFollowingSibling (target)));
alert ("getFollowing:  \n"        + getId (getFollowing (target)));
alert ("getPrecedingSibling:  \n" + getId (getPrecedingSibling (target)));
alert ("getPreceding:  \n"        + getId (getPreceding (target)));
</script>