Javascript无法读取null的属性“value”

时间:2014-05-22 06:16:01

标签: javascript html arrays

晚安stackoverflow。

我遇到了一个Javascript代码段的问题,它在JSFiddle中有效但在实际HTML上无效。

我有一个关于为什么它不起作用的要点,当调用以下行时:

while (list.firstChild) {

在那个时间点,list的值仍为null。所以它可能会在此时崩溃并烧毁。

然而,为什么它在小提琴中起作用?

我知道我可以通过在列表前面添加一个项目来解决这个问题,以避免使其变为空,但是,我更好奇为什么会出现差异(jsfiddle和html如何不同)以及如何将继续恢复jsfiddle功能。

这项工作的小提琴

http://jsfiddle.net/vSHQD/9/

我的Test.html无效

<script>
var list = document.getElementById('deliveryIdArray');
var names = [];

window.changeText2 = function() {
    var deliveryIdentification = document.getElementById('deliveryIdentification').value;
    names.push(deliveryIdentification);//simply add new name to array;
    //array changed re-render list
    renderList();
}

window.renderList = function(){
    while (list.firstChild) {
        list.removeChild(list.firstChild);
    }
    //create each li again
    for(var i=0;i<names.length;i++){
        var entry = document.createElement('li');
        entry.appendChild(document.createTextNode(names[i]));
        var removeButton = document.createElement('button');
        removeButton.appendChild(document.createTextNode("X"));
        removeButton.setAttribute('onClick','removeName('+i+')');
        entry.appendChild(removeButton);
        list.appendChild(entry);
    }
}


window.removeName = function(nameindex){
    names.splice(nameindex,1);
    //array changed re-render list
    renderList();
}

window.getDeliveries = function(){
    return names;
}
</script>

<html>
    <body>
        <b>Number </b>
        <input id = "deliveryIdentification" name = "deliveryIdentification" type = "text" size = "16" maxlength = "30">

        <!-- Array Area Creation -->
        <input type='button' onclick='changeText2()' value='Add' />

        <ol id="deliveryIdArray">
        </ol>
    </body>
</html>

非常感谢任何和所有的帮助,祝你有个美好的夜晚!

4 个答案:

答案 0 :(得分:1)

你的HTML格式不好。你也可以在最后编写javascript代码,或者你需要window.onLoad函数来确保加载document

<html>
    <body>
        <b>Number </b>
        <input id = "deliveryIdentification" name = "deliveryIdentification" type = "text" size = "16" maxlength = "30">

        <!-- Array Area Creation -->
        <input type='button' onclick='changeText2()' value='Add' />

        <ol id="deliveryIdArray">
        </ol>
    </body>
    <script>
        var list = document.getElementById('deliveryIdArray');
        var names = [];

        window.changeText2 = function() {
            var deliveryIdentification = document.getElementById('deliveryIdentification').value;
            names.push(deliveryIdentification);//simply add new name to array;
            //array changed re-render list
            renderList();
        }

        window.renderList = function(){
            while (list.firstChild) {
                list.removeChild(list.firstChild);
            }
            //create each li again
            for(var i=0;i<names.length;i++){
                var entry = document.createElement('li');
                entry.appendChild(document.createTextNode(names[i]));
                var removeButton = document.createElement('button');
                removeButton.appendChild(document.createTextNode("X"));
                removeButton.setAttribute('onClick','removeName('+i+')');
                entry.appendChild(removeButton);
                list.appendChild(entry);
            }
        }


        window.removeName = function(nameindex){
            names.splice(nameindex,1);
            //array changed re-render list
            renderList();
        }

        window.getDeliveries = function(){
            return names;
        }
    </script>
</html>

或者您可以在加载document时注册处理程序事件:

<html>
    <head>
        <meta charset="utf-8">
        <script>
            document.addEventListener("DOMContentLoaded", init);
            function init(){
                var list = document.getElementById('deliveryIdArray');
                var names = [];

                window.changeText2 = function() {
                    var deliveryIdentification = document.getElementById('deliveryIdentification').value;
                    names.push(deliveryIdentification);//simply add new name to array;
                    //array changed re-render list
                    renderList();
                }

                window.renderList = function(){
                    while (list.firstChild) {
                        list.removeChild(list.firstChild);
                    }
                    //create each li again
                    for(var i=0;i<names.length;i++){
                        var entry = document.createElement('li');
                        entry.appendChild(document.createTextNode(names[i]));
                        var removeButton = document.createElement('button');
                        removeButton.appendChild(document.createTextNode("X"));
                        removeButton.setAttribute('onClick','removeName('+i+')');
                        entry.appendChild(removeButton);
                        list.appendChild(entry);
                    }
                }


                window.removeName = function(nameindex){
                    names.splice(nameindex,1);
                    //array changed re-render list
                    renderList();
                }

                window.getDeliveries = function(){
                    return names;
                }
            };
        </script>
    </head>
    <body>
        <b>Number </b>
        <input id = "deliveryIdentification" name = "deliveryIdentification" type = "text" size = "16" maxlength = "30">

        <!-- Array Area Creation -->
        <input type='button' onclick='changeText2()' value='Add' />

        <ol id="deliveryIdArray">
        </ol>
    </body>
</html>

You could see more about window.onload here.

You could see more about DOMContentLoadhere.

答案 1 :(得分:1)

如果您查看JSFiddle页面的左侧,您会看到第二个下拉列表设置为&#34; onLoad&#34;。

这意味着在onload事件被触发之前你的JavaScript没有执行。

但是,当您将其作为HTML页面包含时,JavaScript会立即执行。这会中断,因为DOM没有准备好,因此你的getElement函数不会返回你期望的值。

您可以通过将下拉列表的值更改为&#34;无包装头&#34;来重现JsFiddle中的问题。并重新运行。

已经有great answers关于如何连接DOM以便在DOM加载后运行。

您还可以使用文档就绪事件而不是onload事件(等待加载图像之类的事件)。优点是您的JavaScipt可能会更快执行。

window.onload vs $(document).ready()

答案 2 :(得分:1)

有一个脚本错误:

Unable to get value of the property 'firstChild': object is null or undefined 

将您的列表放在window.renderList函数中,它将解决问题。

window.renderList = function(){

var list = document.getElementById('deliveryIdArray');

    while (list.firstChild) {
        list.removeChild(list.firstChild);
    }
    //create each li again
    for(var i=0;i<names.length;i++){
        var entry = document.createElement('li');
        entry.appendChild(document.createTextNode(names[i]));
        var removeButton = document.createElement('button');
        removeButton.appendChild(document.createTextNode("X"));
        removeButton.setAttribute('onClick','removeName('+i+')');
        entry.appendChild(removeButton);
        list.appendChild(entry);
    }
}

答案 3 :(得分:1)

这是一个有趣的问题,

虽然这是我第一次看到人们把脚本标签输出html标签。

我的案例中的Web浏览器引擎(webkit)从上到下呈现html,

目前,脚本引擎执行var list = document.getElementById('deliveryIdArray'); dom元素deliveryIdArray dom树中不存在,因此,它无法找到元件。

将脚本标记放在文件底部后,您可以看到样本快乐地运行。

这就是为什么在js idiom中,人们喜欢将js放在html文件的底部, 或者您需要在DOMContentLoad事件中连接处理程序或使用jquery方式$(function(){});