从返回“Undefined”

时间:2017-07-02 13:00:38

标签: javascript

我要做一个待办事项列表。在我的'editTaskEnter'上,我只是试着在它上面调用'editTask'。

现在我可以复制'editTask'中的所有代码并将其复制到'EditTaskEnter'并且它工作正常,但这是很多代码重复。相反,当用户点击进入时,我只想调用editTask函数。

我得到的问题是变量的范围。

我收到此错误:'未捕获TypeError:无法读取未定义'的属性'querySelector'。

我想如果我在'editTask'中返回每个变量,就可以在我的'editTaskEnter'函数中访问它们。显然不是:)。

任何想法为什么?

JS

// To do list

// Cache DOM
var addToDo = document.getElementById('add-to-do');
var taskHolder = document.getElementById('task-holder');
var uncompleteTasks = document.getElementById('uncompleted-tasks');
var completedTasks = document.getElementById('completed-tasks');

// Bind events
var bindEvents = function(listItem, checkboxEventHandler) {
  // Delete
  var deleteToDo = listItem.querySelector('.delete-to-do');
  deleteToDo.addEventListener('click', deleteTask);
  // Edit
  listItem.querySelector('.edit-to-do').addEventListener('click', editTask);
  listItem.querySelector('.edit-holder').addEventListener('keyup', editTaskEnter);
  // Checkbox
  var checkbox = listItem.querySelector('input.edit-to-do');
  checkbox.onchange = checkboxEventHandler;
}

// Create list item
var createListItem = function() {
  var listItem = document.createElement('li');
  var deleteToDo = document.createElement('button');
  deleteToDo.innerHTML = 'delete';
  deleteToDo.classList.add('delete-to-do');
  var editToDo = document.createElement('button');
  editToDo.innerHTML = 'edit';
  editToDo.classList.add('edit-to-do');
  var toDoStatus = document.createElement('input');
  toDoStatus.type = 'checkbox';
  toDoStatus.classList.add('edit-to-do');
  var editHolder = document.createElement('input');
  editHolder.type = 'text';
  editHolder.classList.add('edit-holder');

  listItem.appendChild(deleteToDo);
  listItem.appendChild(editToDo);
  listItem.appendChild(toDoStatus);
  listItem.appendChild(editHolder);

  return listItem;
}

// Add task
var addTask = function(e) {
  var taskHolderValue = taskHolder.value;
  if(taskHolderValue) {
    var taskHolderElement = document.createElement('label');
    taskHolderElement.classList.add('to-do-item');
    taskHolderElement.innerHTML = taskHolderValue;
    var listItem = createListItem();
    listItem.insertBefore(taskHolderElement, listItem.childNodes[0]);
    uncompleteTasks.appendChild(listItem);
    bindEvents(listItem, taskCompleted);

    taskHolder.value = '';
  } else {
    alert("You didn't add a to a to do!");
  }
}

var addTaskEnter = function(e) {
  var key = 'which' in e ? e.which : e.keyCode;
  if(key === 13) {
    addTask();
  }
}

// Delete task
var deleteTask = function() {
  var listItem = this.parentNode;
  console.log(listItem);
  var parentItem = listItem.parentNode;
  parentItem.removeChild(listItem);
}

// Edit task
var editTask = function() {
  var defaultValue = this.parentNode.querySelector('label').innerHTML;
  var listItem = this.parentNode;
  var listParent = this.parentNode;
  var editedValue = listParent.querySelector('input.edit-holder').value;
  if(listItem.classList.contains('editing') && editedValue) {
    listParent.querySelector('label').innerHTML = editedValue;
  } else {
    defaultValue;
  }
  listItem.classList.toggle('editing');

  return defaultValue;
}

// Edit task enter
var editTaskEnter = function(e) {
  var key = 'which' in e ? e.which : e.keyCode;
  if(key === 13) {
    editTask();
  }
}

// Task completed
var taskCompleted = function() {
  var listItem = this.parentNode;
  completedTasks.appendChild(listItem);
  this.parentNode.classList.add('completed');
  bindEvents(listItem, taskUncompleted);
}

// Task uncompleted
var taskUncompleted = function() {
  var listItem = this.parentNode;
  uncompleteTasks.appendChild(listItem);
  this.parentNode.classList.remove('completed');
  bindEvents(listItem, taskCompleted);
}

// Add task
addToDo.addEventListener("click", addTask);
taskHolder.addEventListener("keyup", addTaskEnter);

// Loop over uncomplete tasks
for(i=0; i<completedTasks.length; i++) {
  var listItem = completedTasks[i];
  uncompleteTasks.appendChild(listItem);
  bindEvents(listItem, completedTasks);
}

1 个答案:

答案 0 :(得分:2)

当你调用这样的JavaScript函数:myFunction()时,函数中的this对象将是对全局对象的引用。

这正是您在editTask中致电editTaskEnter时所发生的情况。 this将指向没有window属性的全局对象(parentNode)。因此this.parentNodeundefined,而undefined没有名为querySelector的方法。

editTaskEnter功能修改为以下功能应该可以正常工作:

// Edit task enter
var editTaskEnter = function (e) {
  if(e.key === 'Enter') {
    editTask.call(this);
  }
}

editTask.call(this)会导致this中的editTask对象与editTaskEnter中的对象相同。