[英]Getting an uncaught reference error in javascript on a variable that is said to be undefined. I have no idea why
My problem comes from when I try to add a new task from the tasker_matic.js file. 我的问题来自于当我尝试从tasker_matic.js文件添加新任务时。 Over in the tasker.js file, I get the following error:
在tasker.js文件中,我收到以下错误:
tasker.js:196 Uncaught ReferenceError: task is not defined
at Object.add (tasker.js:196)
at addTask (tasker_matic.js:157)
at HTMLInputElement.onclick (tasker.html?username=smaug&password=dragon:42)
Again, I have no idea why I am getting this error. 再说一遍,我不知道为什么我会收到这个错误。 I am now allowed to make any changes to tasker.js.
我现在可以对tasker.js进行任何更改。
Here is the relevant sections of code: 以下是相关的代码部分:
tasker_matic.js: tasker_matic.js:
function addTask() {
let task = {};
let description = document.getElementById('descField').value;
let time = document.getElementById('dField').value;
let colorCode = document.getElementById('cField').value;
task.desc = description;
task.due = time;
task.color = colorCode;
tasker.add(userId, task, (err, task) => {
if (err) {
alert('Broken');
}
});
}
tasker.js: tasker.js:
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 );
}
}
}
})();
tasker.html: tasker.html:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Tasker</title>
<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.js"></script>
<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>
There could be a naming problem with this specific method in tasker.js 在tasker.js中,这个特定方法可能存在命名问题
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);
}
},
The parameter task
is overriden by the newly declared variable task
. 参数
task
被新声明的变量task
覆盖。 Try to change this up and see what happens. 尝试改变这一点,看看会发生什么。
Abana's answer identifies the problem area, so I'll expand on why this doesn't work. Abana的答案确定了问题区域,因此我将扩展为什么这不起作用。
When you use let
, similar to var
the variable declaration is hoisted to the top of the scope. 当你使用
let
,类似于var
,变量声明被提升到范围的顶部。 The difference is that it also creates a Temporal Dead Zone (TDZ) during which any attempt to access the variable throws an error. 不同之处在于它还会创建一个临时死区 (TDZ),在此期间任何访问该变量的尝试都会引发错误。
Now looking at the code, because you start the line with let task
it creates a new variable in that block's scope, but the TDZ lasts until after that line executes to completion. 现在查看代码,因为你使用
let task
开始行,它会在该块的作用域中创建一个新变量,但是TDZ会持续到该行执行完成之后。 When it goes to create a new Task
, it accesses the inner scoped task
, during the TDZ period and throws an error. 当它创建一个
new Task
,它会在TDZ期间访问内部作用域task
并抛出错误。
The solution here, is to use a different variable name: 这里的解决方案是使用不同的变量名称:
add: function (ownerId, task, cb) {
if (state.user.id == ownerId) {
if (task.desc && task.due && task.color) {
let due = new Date(task.due);
let innerTask = new Task(task.id, ownerId, task.desc, due, task.color, Boolean(task.complete));
state.users[ownerId].tasks[task.id] = innerTask;
respond(null, innerTask, cb);
} else {
respond('invalid task', null, cb);
}
} else {
respond('forbidden', null, cb);
}
},
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.