V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
islujw
V2EX  ›  JavaScript

写 JS 为去除特定 class 下的第一个 p 元素,浏览器没报错,但无效果

  •  
  •   islujw · 2017-08-09 21:41:24 +08:00 · 3602 次点击
    这是一个创建于 2648 天前的主题,其中的信息可能已经有所发展或是发生改变。

    HTML 是这样的:

    <div class="accordion">
    	<div class="spoiler">
    		<div class="content">
            		<p></p>
                    	<p>正文</p>
    		</div>
    	</div>
    </div>
    

    因为正文外的 div 元素是插件生成的,总是会出现第一个多余的 p 元素,希望在后面加个 js 来去除。

    上面的 HTML 段落从 .spoiler 开始的部分共 6 个排比,都在 .accordion 内。我在「正文」的 p 元素标签内加了 id="cleanX",X 是从 1 ~ 6 的数字,按顺序分布在 6 个排比的结构里面。

    接着按如下写的 js,浏览器无报错,但没有效果:

    <script>
    	for (var i=1;i<7;i++) {
    		function cleanTag(i) {
        			var x = document.getElementById("clean"+i);
            		var y = x[i];
            		y.parentNode.removeChild(1);
    		}
    	}
    </script>
    

    问题在哪儿?要怎么解决这个问题呢?

    29 条回复    2017-08-28 11:53:30 +08:00
    ferrum
        1
    ferrum  
       2017-08-09 21:43:51 +08:00
    你的函数执行了吗?

    另外 getElementById 返回单个 Node 节点,不是数组。没有具体的 HTML,其实也不好看出真正的问题……
    piku
        2
    piku  
       2017-08-09 21:46:57 +08:00 via Android
    你的 for 里定义了一个 function,但是这个 function 在什么时候执行呢?
    leeg810312
        3
    leeg810312  
       2017-08-09 21:54:12 +08:00 via Android
    function 不是闭包,根本没有执行
    napsterwu
        4
    napsterwu  
       2017-08-09 22:01:38 +08:00
    (function(i){}) (i)
    Sanko
        5
    Sanko  
       2017-08-09 22:02:58 +08:00 via Android
    没执行吧
    qiayue
        6
    qiayue  
       2017-08-09 22:08:35 +08:00
    一个函数定义了其次
    blackywkl
        7
    blackywkl  
       2017-08-09 23:00:07 +08:00
    getElementById 返回的是 Dom 对象吧,为什么 x[i] ?
    chinvo
        8
    chinvo  
       2017-08-09 23:02:09 +08:00
    函数没执行
    islujw
        9
    islujw  
    OP
       2017-08-10 00:25:46 +08:00
    @blackywkl 赋给 y,document.getElementById("clean1") 用后面的方法。
    Lax
        10
    Lax  
       2017-08-10 02:06:44 +08:00
    一个 function 声明了 6 遍 ;->
    msg7086
        11
    msg7086  
       2017-08-10 02:25:17 +08:00
    你定义了一个函数六次,并且一次都不去执行……?
    autoxbc
        12
    autoxbc  
       2017-08-10 03:01:39 +08:00   ❤️ 2
    我觉得一句话提示可能不够说明问题

    1. 不应该在循环内部定义函数,效率很差,要这么写
    var cleanTag = function(i)
    {
    // doSomething
    };
    for(var i=1 ; i<7 ; i++ )
    {
    cleanTag(i);
    }

    2. 定义的函数并没有实际执行,没有传递参数

    3. 如果希望函数获取外部的变量值(i),或者传递参数(实参),或者不定义形参,让函数内部代码在作用域链里查找

    传递实参
    (function(i){
    // doSomething
    })(i);

    从作用域链中查找
    var i;
    (function(){
    // doSomething with i
    })();

    4. 变量 x 存储的是 getElementById 的返回值,这是一个元素节点,就是你需要删除的节点,后面再赋值给 y 没有意义

    5. removeChild 的参数是一个节点,不是数字或者索引值
    删除 x 这么写
    x.parentNode.removeChild(x);

    需要达到题目中的目的,一般不用题目的做法,而是这样
    [].slice.call( document.querySelectorAll('.content p') ).forEach(function(e){
    if( e.textContent.trim() == '' )
    e.parentNode.removeChild(e);
    });

    如果确实已经完成了添加 'clean' 标记,也可以这么写
    [].slice.call( document.querySelectorAll('.content p[id^="clean"]') ).forEach(function(e){
    e.parentNode.removeChild(e);
    });

    最后,楼主可能对自己的代码更亲切,按你的风格可以这样改
    for(var i=1 ; i<7 ; i++ )
    {
    (function(i){
    var x = document.getElementById("clean"+i);
    if(x)
    x.parentNode.removeChild(x);
    })(i);
    }

    P.S. 虽然 js 给人一种上手就能写的感觉,不过如果已经写了几千行代码,最好找本书系统看一下,完全自己摸索会很快达到瓶颈。
    b0x
        13
    b0x  
       2017-08-10 03:01:48 +08:00
    楼主已经从入门到放弃了
    mingl0280
        14
    mingl0280  
       2017-08-10 05:22:14 +08:00   ❤️ 1
    强行在 for 里定义一个函数六次却不执行 233333 当然没报错
    removeChild 用法也是错的。
    而且完全看不出来这个函数干啥的。
    正确做法:
    <script>
    for (var i=1;i<7;i++) {
    function cleanTag(i) {
    var x = document.getElementById("clean"+i);
    x.parentNode.removeChild(x);
    }(i);
    }
    </script>

    或者
    <script>
    for (var i=1;i<7;i++) {
    var x = document.getElementById("clean"+i);
    x.parentNode.removeChild(x);
    }
    </script>
    fox0001
        15
    fox0001  
       2017-08-10 06:25:26 +08:00 via Android
    都说得很清楚了,我就不 BB 了
    ZhLTE
        16
    ZhLTE  
       2017-08-10 09:17:56 +08:00
    楼主加油-。- 该好好学习了
    Anshi
        17
    Anshi  
       2017-08-10 09:27:43 +08:00
    学会 debug 断点调试。
    ahonn
        18
    ahonn  
       2017-08-10 09:33:34 +08:00
    12 楼已经讲得很清楚了。建议你还是先去看书吧..
    SourceMan
        19
    SourceMan  
       2017-08-10 09:59:01 +08:00
    你定义了 6 次 cleanTag function 缺没有执行它
    uvw
        20
    uvw  
       2017-08-10 10:02:00 +08:00
    这应该是个找错及代码优化的问题
    stillsilly
        21
    stillsilly  
       2017-08-10 10:06:36 +08:00
    ……
    autoxbc
        22
    autoxbc  
       2017-08-10 10:41:21 +08:00   ❤️ 1
    很多人说楼主定义了 6 次 cleanTag 函数,我的回答也说这样有性能问题
    刚测试了一下,这个说法需要修正

    循环或者任何语句中的函数声明,并不像函数表达式一样被实际执行,即函数声明不参与流程控制。
    函数表达式作为语句,参与流程控制,有性能开销;函数声明完全没有,哪怕其在一个循环中,使其形式上类似重复多次。或者在一个根本不会执行的流程分支中。

    看这个代码

    console.log( fun.toString() )
    if(0)
    {
    function fun(){return 1}
    }

    // function fun(){return 1}

    函数声明的实际流程是,在代码预解析时(词法分析,语法分析,AST 生成),由引擎将函数声明抽出,放入对应的作用域;在程序执行时,声明语句会被完全略过。

    进一步猜测,只要作用域关系正确,函数声明可以写在代码的任何位置,而不产生副作用。
    daisyxdx
        23
    daisyxdx  
       2017-08-10 10:52:48 +08:00
    好瞎的代码。。。
    winglight2016
        24
    winglight2016  
       2017-08-10 11:17:40 +08:00
    你的标签只有定义 class,寻找的时候又是 byId,这能找到正确的 tag 吗?
    islujw
        25
    islujw  
    OP
       2017-08-10 18:38:25 +08:00
    第一次接触 js,谢谢大家的提醒。确实是一个比较低级的错误。
    islujw
        26
    islujw  
    OP
       2017-08-10 18:39:38 +08:00
    @winglight2016 我已经写了:在「正文」的 p 元素标签内加了 id="cleanX"。
    islujw
        27
    islujw  
    OP
       2017-08-10 18:58:25 +08:00
    @autoxbc 谢谢,非常详细。函数位置的问题是个疏忽,放在循环外面,逻辑上更好。主要是内部的方法,感谢指点。
    mingyun
        28
    mingyun  
       2017-08-12 10:24:25 +08:00
    12 楼厉害了
    flowfire
        29
    flowfire  
       2017-08-28 11:53:30 +08:00
    removeChild 使用方法
    dom.parentNode.removeChild(dom)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2761 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 13:49 · PVG 21:49 · LAX 05:49 · JFK 08:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.