Здравствуйте.
В теле документа у меня прописано
<div id="okno_print"></div>
<script>
dir = "subscribe/mdadmin/p_ajax/";
function get_users() {
document.getElementById("okno_print").innerHTML = "<a href='#' onclick='confirmJS(\"delet\"," + activate_delete_users + ");return false;'>test</a>";
}
function confirmJS(num = false, funct = false) {
alert(dir); //тут нормально
funct(num);
return false;
}
function activate_delete_users(op_users) {
alert(dir); //тут пусто
}
get_users();
</script>
Объясните, почему в функции, которая передается в виде аргумента пустая переменная dir ? Спасибо
При собирании строки с html обработчиками событий, нужно быть предельно осторожным.
Для того, чтобы понять, почему работает именно так, нужно разобраться, что вообще происходит в данном примере.
Необходимо определить, какая строка в итоге получается.
Строка
"<a href='#' onclick='confirmJS(\"delet\","+activate_delete_users+");return false;'>test</a>"
Преобразуется в следующую
"<a href="#" onclick="confirmJS('delet',function activate_delete_users(op_users) { alert(dir); });return false;">test</a>"
Таким образом в функцию confirmJS передается не уже определенная функция, а вновь созданная.
При этом, важной особенностью inline обработчиков является то, что они создаются в контексте html элемента, это означает, что this
в строке
"<a href="#" onclick="console.log(this);return false;">test</a>"
будет ссылаться на элемент a
, по которому кликнули. Кроме этого, все переменные используемые в строке обработчика в первую очередь будут искаться в элементе a
.
Если посмотреть свойства элемента a
, можно увидеть в них свойство dir
наследуемое от HTMLElement.
Значение именно этого свойства и выводится в данном случае.
Исправить поведение можно с помощью нескольких способов:
Не собирать строку вообще, а создавать элементы вручную. Например так:
var deleteButton = document.createElement('a');
deleteButton.href = '#';
deleteButton.textContent = 'Test';
deleteButton.addEventListener('click', function() {
confirmJS('delet', activate_delete_users);
return false;
});
document.getElementById("okno_print").appendChild(deleteButton);
Этот вариант позволит избежать всех проблем связанных с собиранием строки.
Не вставлять в строку функцию. Это позволит избежать создание этой функции при каждом клике в контексте элемента. Строка в этом случае будет выглядеть следующим образом (метод из комментария @Igor)
"<a href='#' onclick='confirmJS(\"delet\", activate_delete_users);return false;'>test</a>"
В этом случае, при создании обработчика будет использована ссылка на существующую функцию activate_delete_users.
Так как в функции используется глобальная переменная, к ней можно получить доступ как к свойству объекта window.
function activate_delete_users(op_users) {
alert(window.dir); //тут уже не пусто
}
Переименовать глобальную переменную, например:
directory = "subscribe/mdadmin/p_ajax/";
Пример:
var dir = "subscribe/mdadmin/p_ajax/";
var directory = "subscribe/mdadmin/p_ajax/";
function get_users() {
wayFour();
wayThree();
wayTwo();
wayOne();
}
function wayOne() {
var deleteButton = document.createElement('a');
deleteButton.href = '#';
deleteButton.textContent = 'Way 1';
deleteButton.addEventListener('click', function() {
confirmJS('delet', activate_delete_users);
return false;
});
document.getElementById("okno_print").appendChild(deleteButton);
}
function wayTwo() {
document.getElementById("okno_print").innerHTML += "<a href='#' onclick='confirmJS(\"delet\", activate_delete_users);return false;'>Way 2</a> ";
}
function wayThree() {
document.getElementById("okno_print").innerHTML += "<a href='#' onclick='confirmJS(\"delet\", " + activate_delete_users_way_3 + ");return false;'>Way 3</a> ";
}
function wayFour() {
document.getElementById("okno_print").innerHTML += "<a href='#' onclick='confirmJS(\"delet\", " + activate_delete_users_way_4 + ");return false;'>Way 4</a> ";
}
function confirmJS(num = false, funct = false) {
console.log('confirmJS', dir);
funct(num);
return false;
}
function activate_delete_users(op_users) {
console.log('activate_delete_users', dir);
}
function activate_delete_users_way_3(op_users) {
console.log("activate_delete_users_way_3", window.dir); //тут уже не пусто
}
function activate_delete_users_way_4(op_users) {
console.log("activate_delete_users_way_4", directory); //тут уже не пусто
}
get_users();
<div id="okno_print"></div>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Вопрос: практикуюсь в JavaScript по одноименной книжке, решил написать запрос на ресурс через Promises, однако они возвращают undefinedВ чем может быть...
Всем доброго пятничного дняКак я писал ранее, я изучаю JavaScript по книге Хавербеке