Почему я получаю ошибку неперехваченной ссылки при попытке доступа к этой глобальной переменной?

У меня есть глобальная переменная в одном файле javascript, и я пытаюсь получить к ней доступ из другого, но она не работает. Я не могу понять почему. Вот весь соответствующий код.

Полный файл библиотеки javascript:

let tasker = (function () {
    let verbs = [
        "make",
        "install",
        "update",
        "generate data for",
        "talk to",
        "schedule a time for",
        "develop a plan for",
        "knit",
        "create",
        "build",
        "write",
        "get",
        "finish",
        "call",
        "arrange",
        "submit",
        "talk to",
        "do",
        "protest",
        "collect",
        "shop for"
    ];

    let nouns = [
        "a cake",
        "the boat",
        "our wedding",
        "the garage",
        "the tow truck",
        "our shed",
        "1090 tax form",
        "the IRS agent",
        "milk",
        "some LED lights",
        "monthly budget",
        "marketing plan",
        "the flowers",
        "an albatross"
    ];

    let userNames = [
        "frodo baggins",
        "gandalf gray",
        "smaug dragon"
    ];

    let Task = function (id, ownerId, desc, due, color, complete) {
        this.ownerId = ownerId;
        this.desc = desc;
        this.due = due;
        this.color = color;
        this.complete = complete;
        this.id = id || randomId();
    };

    let randomId = function () {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    let randomColor = function () {
        let pad = function (v) {
            return v.length == 1 ? '0' + v : v;
        }
        r = Math.floor(Math.random() * 256).toString(16);
        g = Math.floor(Math.random() * 256).toString(16);
        b = Math.floor(Math.random() * 256).toString(16);
        return '#' + pad(r) + pad(g) + pad(b);
    }

    let randomDate = function () {
        year = Math.floor(Math.random() * 14 + 2010);
        month = Math.floor(Math.random() * 12);
        day = Math.floor(Math.random() * 31);
        return new Date(year, month, day);
    };

    let choose = function (things) {
        let i = Math.floor(Math.random() * things.length);
        return things[i];
    }

    let randomDescription = function () {
        return choose(verbs) + ' ' + choose(nouns);
    };

    let makeList = function (ownerId, n) {
        result = [];
        for (i = 0; i < n; i += 1) {
            result.push(new Task(null,
                ownerId,
                randomDescription(),
                randomDate(),
                randomColor(),
                choose([true, false])));
        }
        return result;
    }

    let updateTask = function( oldTask, editedTask ) {
        let propertiesToCopy = ['desc', 'due', 'color', 'complete' ];
        propertiesToCopy.forEach( prop => {
            if ( editedTask.hasOwnProperty( prop ) ) {
                oldTask[prop] = editedTask[prop];
            }
        });
    }

    let state = {
        users: userNames.reduce(function (acc, cv) {
            let parts = cv.split(' '); //
            let name = parts[0];
            let email = parts[0][0] + parts[1] + '@uwlaxer.edu';
            let id = randomId();
            let password = parts[1];
            let tasks = makeList(id, Math.random() * 50 + 20).reduce((acc, t) => { acc[t.id] = t; return acc; }, {});
            acc[id] = {
                name: name,
                email: email,
                id: id,
                password: password,
                tasks: tasks
            };
            return acc;
        }, {}),
        user: null
    };

    let getTask = function (ownerId, id) {
        try {
            return state.users[ownerId].tasks[id];
        } catch (e) {
            return null;
        }
    }

    let getUserByName = function (name) {
        for (id in state.users) {
            if (state.users[id] && state.users[id].name === name) {
                return state.users[id];
            }
        }
        return null;
    }

    let taskList = function (ownerId) {
        let result = [];
        for (let tid in state.user.tasks) {
            result.push(state.user.tasks[tid]);
        }
        return result.sort((a, b) => b.due.getTime() - a.due.getTime());
    }

    let respond = function (error, value, cb) {
        window.setTimeout(() => cb(error, value), Math.random() * 1500);
    }

    let copyTask = function( task ) {
        return new Task(task.id, task.ownerId, task.desc, task.due, task.color, task.complete);
    }

    return {
        login: function ( username, passwd, cb) {
            let user = getUserByName( username );
            if (user && user.password === passwd) {
                state.user = user;
                let cleansedUser = { name: user.name, email: user.email, id: user.id };
                respond(null, cleansedUser, cb);
            } else {
                respond('forbidden', null, cb);
            }
        },

        logout: function (cb) {
            state.user = null;
            respond(null, true, cb);
        },

        tasks: function (ownerId, cb) {
            if (ownerId === state.user.id) {
                let tasks = taskList(ownerId).map(u => new Task(u.id, u.ownerId, u.desc, u.due, u.color, u.complete));
                respond(null, tasks, cb);
            } else {
                respond('forbidden', null, cb);
            }
        },

        add: function (ownerId, task, cb) {
            if (state.user.id == ownerId) {
                if (task.desc && task.due && task.color) {
                    let due = new Date(task.due);
                    let task = new Task(task.id, ownerId, task.desc, due, task.color, Boolean(task.complete));
                    state.users[ownerId].tasks[task.id] = task;
                    respond(null, task, cb);
                } else {
                    respond('invalid task', null, cb);
                }
            } else {
                respond('forbidden', null, cb);
            }
        },

        delete: function (ownerId, taskId, cb) {
            if (state.user.id === ownerId) {
                let task = state.users[ownerId].tasks[taskId];
                delete state.users[ownerId].tasks[taskId];

                if (task) {
                    respond(null, task, cb);
                } else {
                    respond('no such task', null, cb);
                }
            } else {
                respond('forbidden', null, cb);
            }
        },

        edit: function (ownerId, taskId, task, cb) {
            if (state.user.id == ownerId) {
                if (taskId) {
                    let oldTask = getTask(ownerId, taskId);
                    if ( oldTask) {
                        updateTask( oldTask, task );                        
                        respond( null, copyTask( oldTask ), cb );
                    } else {
                        respond( 'no such task', null, cb );
                    }                    
                } else {
                    respond( 'no such task', null, cb );
                }
            } else {
                respond( 'forbidden', null, cb );
            }
        }
    }

})();

Функция Я пытаюсь получить доступ к глобальной переменной из:

function login(e) {
    var userName = document.getElementById("usernameInput").value;
    var password = document.getElementById("passwordInput").value;
    console.info("hi");
    tasker.login( userName, password, (err, user => {
        if (err) {
            alert( err );
        }
        else {
            var s = document.getElementById("home");
            s.style.visibility = 'hidden';
        }
    }));
}

Сопровождающий документ HTML:

<!DOCTYPE html>
<html lang = "en" xmlns = "http://www.w3.org/1999/xhtml">
<head>
    <meta charset = "utf-8" />
    <title>Tasker</title>
    <script src = "tasker.js"></script>
    <link rel = "stylesheet" href = "tasker_matic.css">
    <link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <script src = "tasker_matic.js"></script>    
</head>
<body>
  <div class = "container">

    <div id = "login" class = "on">
      <h1>Login</h1><br>
        <form style = "width:50%">
          <input id = "usernameInput" type = "text" name = "username" placeholder = "Username" class = "form-control">
          <input id = "passwordInput" type = "password" name = "password" placeholder = "Password" class = "form-control">
          <input type = "submit" value = "Login" class = "btn btn-primary pull-right" onclick = "login(event)">
        </form>
    </div>

    <div id = "home" class = "off">
      <h1>Tasker <small><span class = "pull-right btn btn-primary btn-sm" id = "logout" onclick = "logout()"></span></small></h1>
      <div class = "well well-sm">
        <form class = "form-inline">
          <div class = "form-group">
            <label for = "descField">Description</label>
            <input class = "form-control" type = "text" placeholder = "Description" id = "descField">
          </div>

          <div class = "form-group">
            <label for = "cField">Color Code</label>
            <input class = "form-control" type = "color" id = "cField"/>
          </div>

          <div class = "form-group">
            <label for = "dField">Due Date</label>
            <input class = "form-control" type = "date" id = "dField"/>
          </div>

          <input class = "form-control" type = "button" value = "+" id = "addButton" onclick = "addTask()"/>
        </form>
      </div>

      <div class = "well well-sm">
        <form class = "form-inline">
          <input class = "form-control" type = "text" placeholder = "search" id = "searchField" style = "width:25%" onkeyup = "searchTextChange()"/>
          <div class = "checkbox">
            <label>
              <input type = "checkbox" id = "incompleteBox" onclick = "incompleteChange()"/>Incomplete Only
            </label>

          </div>
          <div class = "checkbox">
            <label>
              <input type = "checkbox" id = "overdueBox" onclick = "overdueChange()"/>Over-due only
            </label>
          </div>
        </form>
      </div>

      <table id = "tasks" class = "table table-striped">
      </table>
    </div>
  </div>
</body>
</html>

Любая помощь будет очень признательна. Я просто не понимаю, что происходит.

Вы не собираетесь называть имя этой глобальной переменной ..?

Teemu 03.12.2018 06:45
tasker.login(userName, password, (err, user => { - это одна проблема, вы используете оператор запятой, вы, вероятно, хотели использовать вместо этого (err, user)
CertainPerformance 03.12.2018 06:46

Мне так жаль. Это таскер.

Wesley Brandt 03.12.2018 06:46

используйте var вместо let при определении таскера. Проверьте правила определения объема работ.

dRoyson 03.12.2018 06:48

Или явно назначить window.tasker

CertainPerformance 03.12.2018 06:49

Или вы можете заменить его на function tasker(){ }. Дизайн и реализация будут такими же, хотя и с меньшим количеством скобок. Вы все равно назначаете IIFE переменной, в чем смысл. Просто сделайте это регулярной функцией и покончите с этим. Он будет иметь свою собственную область видимости и предотвращать загрязнение глобального пространства имен, как обычно ... как и должно быть.

Abana Clara 03.12.2018 07:07

К сожалению, я вообще не могу изменить документы html и глобальных переменных.

Wesley Brandt 03.12.2018 07:21
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
7
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

err, user => { заменить на (err, user) => {

tasker уже является глобальной переменной:

tasker is already a global variable

Почему это должно иметь значение?

Felix Kling 03.12.2018 07:37
tasker.login( userName, password, (err, user => { }));(err, user => { })err - это не параметр, а переменная. tasker.login( userName, password, (err, user) => { });
山茶树和葡萄树 03.12.2018 07:47

Что ж, после того, как вы изменили свой ответ, это имеет смысл;)

Felix Kling 03.12.2018 07:57

Добавьте файлы Jquery.min.js и bootstrap.min.js первыми приоритетами, затем добавьте свои собственные файлы js

приведенный ниже код является стандартным форматом начальной загрузки

   <!DOCTYPE html>
    <html lang = "en">
      <head>
        <meta charset = "utf-8">
        <meta http-equiv = "X-UA-Compatible" content = "IE=edge">
        <meta name = "viewport" content = "width=device-width, initial-scale=1">
        <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
        <title>Bootstrap 101 Template</title>

        <!-- Bootstrap -->
        <link href = "css/bootstrap.min.css" rel = "stylesheet">

        <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
        <!--[if lt IE 9]>
          <script src = "https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
          <script src = "https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
        <![endif]-->
      </head>
      <body>
    <h1>Hello, world!</h1>

    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <script src = "js/bootstrap.min.js"></script>
  </body>
</html>

Другие вопросы по теме

Как я могу заставить этот отключенный ввод действовать как включенный и прокручивать при нажатии кнопок?
Сайт замедляется после загрузки файла данных JSON размером 50 МБ
Как я могу отредактировать размер заднего фонового поля, чтобы он соответствовал внутренним ящикам с помощью node.js
При использовании атрибута name с ngModel в теге формы ошибка по-прежнему возникает - «Если ngModel используется в теге формы, необходимо установить атрибут name ...»
Мое фоновое изображение не раскрывается полностью или не отображается в полном размере. Проблема с фоновым изображением в разделе html
Предотвращение переноса div на меньший экран html css
Как сделать POST-запрос в HTML, не открывая новую вкладку
Тег HTML To @ Html.ActionLink в ASP.NET MVC5
Откройте iFrame при нажатии на значок расширения Chrome
Выберите тег и материализуйте датапикер, исчезающий при отправке формы в React