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

Сценарий заключается в том, что я хочу изменить URL-адрес через раскрывающуюся форму, используя комбинацию Javascript и HTML. Если я помещу оператор if else внутри функции, он будет работать безупречно, но в моем сценарии мне нужно поместить его вне функции, и он не работает даже после того, как я сделал переменную глобальной.

Я пробовал несколько решений из вопросов, связанных с моей проблемой, но, похоже, это не работает для моего сценария.

Вот код, который я сейчас использую.

var documentLink = document.getElementById('documentLink');

function getDocument(option) {
  chosenDocument = option.value;
}

if (chosenDocument === "Google") {
  documentLink.href = "https://www.google.com";
} else if (chosenDocument === "duckduckgo") {
  documentLink.href = "https://www.duckduckgo.com";
}
-1
Angga 19 Янв 2022 в 13:26
1
Вы никогда не вызываете getDocument, поэтому chosenDocument никогда не будет установлено.
 – 
Ivar
19 Янв 2022 в 13:28
1
Кстати, вы не должны использовать getElementById (ни querySelector) до события DOMContentLoaded, иначе они не будут работать надежно.
 – 
Dai
19 Янв 2022 в 13:28
Ой! поэтому вне функции все, что мне нужно сделать, это добавить getDocument(); ? Извините, если это тривиально, я действительно новичок в JavaScript.
 – 
Angga
19 Янв 2022 в 13:33
Ну, функция не запускается сама по себе. Вам действительно нужно вызвать его, но вы должны сделать это перед строкой chosenDocument === "Google", иначе оно не будет иметь правильного значения.
 – 
Ivar
19 Янв 2022 в 13:35
1
Понятно, спасибо!
 – 
Angga
19 Янв 2022 в 15:06

5 ответов

Лучший ответ

Это, вероятно, то, что вы хотели сделать.

Примечание. Я использую рекомендуемые eventListeners.

window.addEventListener("DOMContentLoaded", function() { // when elements are available in page
  const documentLink = document.getElementById('documentLink');
  
  document.getElementById("searchSites").addEventListener("change", function() {
    const chosenSite = this.value;
    if (chosenSite === "Google") { // this could be done nicer with a lookup table
      documentLink.href = "https://www.google.com";
    } else if (chosenSite === "duckduckgo") {
      documentLink.href = "https://www.duckduckgo.com";
    }
  })
  
  documentLink.addEventListener("click", function(e) { 
    if (this.getAttribute("href") === "") { // not set 
      e.preventDefault(); // stop link
      alert("Please select a site first");
    }
  })
})
<select id="searchSites">
  <option value="">Please select</option>
  <option value="Google">Google</option>
  <option value="duckduckgo">duckduckgo</option>
</select><br/>
<a href="" id="documentLink">GO</a>
0
mplungjan 19 Янв 2022 в 14:53
1
Большое спасибо @mplungjan! Я могу многому научиться из синтаксиса, который вы дали.
 – 
Angga
19 Янв 2022 в 13:57
Пожалуйста. И у вас есть таблица поиска, которую я предложил от Энди.
 – 
mplungjan
19 Янв 2022 в 14:13
Событие load неуместно, поскольку потенциально оно может произойти через минут после полной загрузки HTML. Вместо этого используйте событие DOMContentLoaded, которое является фактической точкой, в которой getElementById и querySelector можно безопасно использовать.
 – 
Dai
19 Янв 2022 в 14:51
Я всегда использовал нагрузку. Кажется, он работает везде, где я его использую, и его текст короче, чем DOMContentLoaded, но я посмотрел на него и теперь буду использовать DOMContentLoaded, если смогу написать его правильно.
 – 
mplungjan
19 Янв 2022 в 14:52

Когда вы помещаете свои коды непосредственно в тело тега «script», он будет выполняться только один раз (при загрузке скрипта). Вам нужно поместить свои коды в место, которое может запускаться более одного раза, например, поместить его в функцию и вызывать ее при возникновении события.

Если вам нужно, чтобы блок «если» запускался каждый раз, когда изменяется раскрывающееся значение, у вас есть следующие варианты: 1- переместите свой код в функцию getDocument 2- переместите блок «если» в новую функцию, а затем вызовите его в функции getDocument.

Или 3- переместите свой блок «если» в новую функцию, а затем назначьте его другому событию, совпадающему с событием выпадающего списка (например, выпадающее меню при изменении или выпадающее меню при размытии)

0
Samir 19 Янв 2022 в 13:37
Я согласился с вашим предложением номер два, и оно работает, большое спасибо, Самир!
 – 
Angga
19 Янв 2022 в 13:53
  1. Оберните код для выполнения в событии DOMContentLoaded.
  2. Переместите функцию getDocument за пределы этого прослушивателя событий.
  3. Я предполагаю, что у вас уже есть прослушиватель событий выбора опции, и у вас есть переменная с именем SelectOption с выбранным значением

Вы можете попробовать следующий код:

<script>
  // Function extracts and returns value from provided parameter
  function getDocumentValue(option) {
    return option.value;
  }

  window.addEventListener('DOMContentLoaded', () => { 
    const documentLink = document.getElementById('documentLink'); // Id is fine if we are sure it wont be duplicated.
    const chosenDocument =  getDocumentValue(SelectOption);

    if (chosenDocument === "Google" ) {
        documentLink.href = "https://www.google.com";
        } else if (chosenDocument === "duckduckgo") {
        documentLink.href = "https://www.duckduckgo.com";
    }   
 })
            
</script>
0
Pavan J 19 Янв 2022 в 13:50
1. Добавьте описание. 2. Если вы используете сниппет, сделайте его рабочим.
 – 
mplungjan
19 Янв 2022 в 13:49
Добавлено описание.
 – 
Pavan J
19 Янв 2022 в 13:53

В комментариях под вашим вопросом изложены ключевые проблемы. Я просто хотел быстро добавить альтернативный подход, который, поскольку вы только начинаете работать с JS, может показаться вам интересным.

// Select the element
const select = document.querySelector('select');

// Add an event listener to it to watch out for changes
// and when that listener is fired call the handleChange function
select.addEventListener('change', handleChange, false);

// Here is an object containing routes
// The keys map directly to the values of the options
const routes = {
  google: 'https://www.google.com',
  duckduckgo: 'https://www.duckduckgo.com'
}

// So that when the function is called all
// we need to do is get the value of that particular route
function handleChange() {
  console.log(routes[this.value]);
}
<select>
  <option disabled selected>Choose</option>
  <option value="google">Google</option>
  <option value="duckduckgo">duckduckgo</option>
</select>

Дополнительная документация

0
Andy 19 Янв 2022 в 14:02
1
Большое спасибо @Andy! Комментарии действительно помогают мне лучше понять. Мне очень жаль, что я пока не могу проголосовать, так как у меня недостаточно представителей, и кажется, что я не могу поставить зеленую галочку более чем на один ответ.
 – 
Angga
19 Янв 2022 в 13:58
Нет проблем, @Angga. Иногда полезно просто помочь людям. Удачного кодирования!
 – 
Andy
19 Янв 2022 в 14:01
PS @Angga Я добавил дополнительную информацию с веб-сайта документации MDN, который вы можете найти полезным.
 – 
Andy
19 Янв 2022 в 14:03
1
Большое спасибо @Andy!
 – 
Angga
19 Янв 2022 в 14:07

Ваша проблема связана с областями действия. Объявите переменную снаружи, чтобы она находилась в области окна, а не в области функции:

var documentLink = document.getElementById('documentLink');
var chosenDocument;

function getDocument(option) {
    chosenDocument = option.value;
}
 
            
if (chosenDocument === "Google" ) {
    documentLink.href = "https://www.google.com";
} else if (chosenDocument === "duckduckgo") {
    documentLink.href = "https://www.duckduckgo.com";
}  

В качестве альтернативы вы можете изменить свою функцию, чтобы она возвращала значение (ее название указывает на то, что она что-то возвращает):

var documentLink = document.getElementById('documentLink');

function getDocument(option) {
    return option.value;
}
 
            
if (getDocument() === "Google" ) {
    documentLink.href = "https://www.google.com";
} else if (getDocument() === "duckduckgo") {
    documentLink.href = "https://www.duckduckgo.com";
}  
-2
shaedrich 19 Янв 2022 в 13:30
Пожалуйста, не минусуйте, не оставив объяснения, почему вы это сделали
 – 
shaedrich
19 Янв 2022 в 13:32
chosenDocument не объявлен в getDocument(), поэтому он не относится к этой функции. Кроме того, учитывая, что getDocument() не вызывается до обращения к chosenDocument, оно все равно не будет содержать ожидаемое значение.
 – 
Ivar
19 Янв 2022 в 13:33