ReferenceError:文档未定义(在纯 JavaScript 中)

IT技术 javascript
2021-02-07 02:32:54

我在尝试时收到“ReferenceError: document is not defined”

var body = document.getElementsByTagName("body")[0];

我之前在其他代码中看到过这一点,并没有造成任何麻烦。为什么是现在?伴随的 HTML 页面只是正文中的一个 div。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/quiz.css" />
    <script type="text/javascript" src="js/quiz.js"></script>
</head>
<body>

    <div id="divid">Next</div>

</body>
</html>

代码如下:

(function(){
        var body = document.getElementsByTagName("body")[0];

        function Question(question, choices, correctAns) {
            this.question = question;
            this.choices = choices;
            this.correctAns = correctAns;
        }

        Question.prototype.checkAns = function(givenAns){
            if (this.correctAns === givenAns) {
                console.log("OK");
            }
        };

        function Quiz() {
            this.questions = [];
        }

        Quiz.prototype.showAllQuestions = function(){
            this.questions.forEach(function(questions){
                console.log(questions.question);
            });
        };

        Quiz.prototype.showQuiz = function(){
            this.questions.forEach(function(questions){

                for (var i=0; i < questions.choices.length; i+=1) {
                    body.innerHTML(
                            "<input type=\"radio\" name=\"sex\" value=\"male\">" 
                            + questions.choices[i] + "<br>");
                }

            });
        };

        var q1 = new Question("What is red?", ["Color","Animal","Building"],1);
        var q2 = new Question("Most popular music?", ["Latin","Pop","Rock"],2);
        var quiz = new Quiz();

        quiz.questions.push(q1);
        quiz.questions.push(q2);
        quiz.showAllQuestions();


        })();

此处尝试此链接中的整个代码

6个回答

这发生在我身上,因为我使用的Next JS是具有服务器端渲染的。当您使用服务器端渲染时,没有浏览器。因此,不会有任何变量windowdocument因此出现此错误。

解决:

如果您使用 Next JS,您可以使用动态渲染来防止组件的服务器端渲染。

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(() => import('../components/List'), {
  ssr: false
})

export default () => <DynamicComponentWithNoSSR />

如果您使用任何其他服务器端渲染库。然后将要在客户端运行的代码添加到componentDidMount. 如果您使用的阵营鱼钩,然后使用useEffects中的位置componentsDidMount

import React, {useState, useEffects} from 'react';

const DynamicComponentWithNoSSR = <>Some JSX</>

export default function App(){

[a,setA] = useState();
useEffect(() => {
    setA(<DynamicComponentWithNoSSR/>)
  });


return (<>{a}<>)
}

参考 :

  1. https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr
  2. https://reactjs.org/docs/hooks-effect.html

这取决于自执行匿名函数何时运行。它有可能在window.document定义之前运行

在这种情况下,尝试添加一个监听器

window.addEventListener('load', yourFunction, false);
// ..... or 
window.addEventListener('DOMContentLoaded', yourFunction, false);

yourFunction () {
  // some ocde

}

更新:(在更新问题并包含代码之后)

阅读以下有关从插入并在head元素中运行的 JavaScript 中引用 DOM 元素的问题
- “getElementsByTagName(...)[0]” 未定义?
- 遍历 DOM

在创建 DOM 之前,JS 可以运行某些实例(例如在插件中)。在发布时,无法检查完整代码。
2021-03-19 02:32:54
IIRCdocument始终定义全局变量,甚至在 DOM 元素完全加载之前。
2021-04-05 02:32:54
啊,说得有道理。
2021-04-14 02:32:54

尝试像这样在 /body 标签之前添加脚本元素

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/quiz.css" />
</head>
<body>

    <div id="divid">Next</div>
    <script type="text/javascript" src="js/quiz.js"></script>
</body>
</html>

您可以为整个组件停用 ssr(检查 Trect 的答案),但它太过分了,因为您只需要跳过 ssr 中的一行。

您应该只检查是否document已定义(确定该函数是否被称为服务器端 - 无文档- 或客户端 - 文档已定义-):

if (typeof document === 'undefined') {
    // during server evaluation
} else {
    // during client's browser evaluation
}

在您的情况下,您不需要在服务器端做任何事情,您可以执行以下操作:

var body = null;

if (typeof document !== 'undefined') {
    // will run in client's browser only
    body = document.getElementsByTagName("body")[0];
}

<script>标签添加“延迟”属性也可以修复它。

<script defer src="yourScript.js"></script>   

在这种情况下,你可以保持<script>里面<head>