问一JS基本问题,关于nextSibling。

2011-03-10 01:13:32 +08:00
 SolidZORO
代码目的是改变<h1>下一个节点的颜色。
由于IE/Fx对nextSibling有不同的判断就必需写function getNextElement 来做判断,随之而来的是一些我搞不明白的问题。


// HTML代码片段
----------------------------------------------------------
<h1> H1 </h1>
<p> PPP </p>
<p> PPP </p>
----------------------------------------------------------


//Javascript代码片段
----------------------------------------------------------
function h1Next() {
if (!document.getElementsByTagName) return false;
var h1s = document.getElementsByTagName("h1");
for (var i=0; i<h1s.length; i++) {
var ppp = getNextElement(h1s[i].nextSibling);
ppp.style.color = "red";
}
}


//书上这样写
function getNextElement(node) {
if (node.nodeType == 1) {
return node;
}
//Q:这个代码我看得有点糊涂。
if (node.nextSibling) {
return getNextElement(node.nextSibling);
}
//Q: 为什么还要返回个null呢?
return null;
}


//我这样写写
function getNextElement(node) {
//如果nodeType是1,就直接返回node(IE),否则继续找下一个节点。(FF)
//Q:我想知道这样写的弊端是什么?
if (node.nodeType == 1) {
return node;
} else {
return node.nextSibling;
}
}

----------------------------------------------------------


以上问题代码出自 《JavaScript DOM 编程艺术》。卡在这里不能理解了。所以求各位指点一下。
5272 次点击
所在节点    问与答
12 条回复
lovekunzi
2011-03-10 01:17:03 +08:00
知之为知之,不知为不知. 反正我是看不懂了.
dismory
2011-03-10 01:37:28 +08:00
递归直到找到元素节点或空后返回。
gonghao
2011-03-10 02:08:32 +08:00
LZ 请注意,书上的写法实际是一种递归的写法,第二个IF后实际是调用自身getNextElement,实际这样完全可以改写成while循环的形式,我承认这种形式有点儿装B~
https://gist.github.com/862657

至于如果LZ明白了这里的意思,自然也就知道自己的写法为什么有缺陷了~

至于这个问题的根本,为什么要做这个判断,LZ应该也是明白了,万恶的兼容性啊~~
gonghao
2011-03-10 02:09:25 +08:00
<script src="https://gist.github.com/862657.js?file=getNextSibling"></script>

貌似刚刚那样发不出去~
gonghao
2011-03-10 02:10:42 +08:00
git://gist.github.com/862657.git

不好意思,刷屏了~~
benzhe
2011-03-10 02:14:28 +08:00
确定你写的那段能达到你预期的效果?原function是个循环,而你的只是一个判断,@dismory 的说法是对的。
gonghao
2011-03-10 02:16:13 +08:00
https://gist.github.com/862657.js

悲剧呀,为啥gist就是没办法贴出来啊?
SolidZORO
2011-03-10 02:24:41 +08:00
@gonghao 了解了。原来是这样。也就是说,在IE下,如果一直有很多null或者空白节点都没关系。他会一直循环找到下一个type==1的节点为止对吧?

我是看不大懂这样的嵌套。return getNextElement(node.nextSibling); 这个能更加详细的解释一下么?


还有你在github上的;
function getNextSibling(ele) {
while (ele = ele.nextSibling) {
if (1 === ele.nodeType) return ele;
}
}

我也看不明白。。。。。1 === ele.nodeType 可以反过来写么? ele.nodeType === 1 这样。
gonghao
2011-03-10 02:48:03 +08:00
@SolidZORO 空白节点这个问题是FF才有滴,主要是由于你的HTML中,两个节点间的换行符可能会导致一个空的TextNode~嗯,你理解了这里为什么要用递归,就是防止存在多个空的TextNode节点~

return getNextElement(node.nextSibling); 这句是典型的递归调用,不清楚的话可以google一下,直观的说法就是,首先判断当前node是不是nodeType为1,否则的话则检查这个node的nextSibling,即当前node = node.nextSibling,由此反复开始判断~那么这个判断什么时候终止呢?乐观情况,找到了所需要的nextSibling,则直接返回(第一个if的return),极端情况就是找不到这样的节点,则返回null(最后的那个return null)

至于我代码里面那个判断,逻辑判断左右操作数交换位置是不存在问题的,这样写的好处是防止误把逻辑判断写成了赋值,即 误将 foo == 1 写成了 foo = 1,如果你用我说的这种写法,1 == foo,误写的话就是1 = foo,这样在执行期间就会报语法错误,很容易排查~

建议学习JS最好还是从语言根本开始,DOM、浏览器部分可以放放,把JS当成一门纯粹的语言来学会好很多~
SolidZORO
2011-03-10 02:56:57 +08:00
@gonghao 嗯。空白节点的确是FF才有的,刚错打成IE了。谢谢你的耐心教导,我这人学程序类的东西没什么天分,逻辑不大好,很多东西一时间也看不明白。经过你一说,我就明白很多之前纠结的问题了。1 === foo 的方式很好,之后我写非赋值的语句也得这样。

之前我还不敢碰JS。因为觉得有点乱七八糟的。现在碰碰,觉得蛮有意思的。 我没什么语言基础。实在是比较困难了。多谢指教。
gonghao
2011-03-10 03:05:53 +08:00
@SolidZORO 呵呵,客气客气了~刚开始都是这样的,慢慢就会好起来的了,多给自己一些信心呢~

反正跟着自己兴趣走嘛,感兴趣就多玩玩呢,呵呵~~
lepture
2011-03-10 11:21:27 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/9534

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX