функция становится неопределенной при передаче другой функции - PullRequest
1 голос
/ 05 мая 2020

Я пытаюсь создать функцию пишущей машинки, но func в функции typewrite становится undefined.

var txtElems = document.querySelectorAll("[data-txt]");
txtElems = Array.from(txtElems);
typewriteAll(txtElems, 70);
function typewriteAll(elemArr, delay) {
	if (elemArr.length) {
		typewrite(
			elemArr[0],
			elemArr[0].dataset.txt,
			delay,
			typewriteAll, elemArr.slice(1), delay
		);
	}
}

function typewrite(Elem, t, delay, func, arg1, arg2) {
	let txt = String(t);
	(txt != "")
		? (() => {
			Elem.innerHTML += txt[0];
			setTimeout(
				() => {
					typewrite(
						Elem,
						txt.slice(1, txt.length),
						delay
					)
				}, delay)
			})()
		: (() => {
			setTimeout(
				() => {
					Elem.setAttribute("typing", "end");
					func(arg1, arg2)
				}, 10 * delay
			);
		})()
}
<div data-txt="Some text to type"></div>
<div data-txt="Some more text to type..."></div>

1 Ответ

2 голосов
/ 05 мая 2020

Вызов функций работает нормально, проблема в том, что внутри обратного вызова typewrite setTimeout (когда вы вспоминаете typewrite) вы забыли передать обратный вызов и его параметры самому себе, поэтому они определены только во время первой итерации.

Чтобы он заработал, передайте все аргументы самому себе:

var txtElems = document.querySelectorAll("[data-txt]");
txtElems = Array.from(txtElems);
typewriteAll(txtElems, 70);
function typewriteAll(elemArr, delay) {
    if (elemArr.length) {
        typewrite(
            elemArr[0],
            elemArr[0].dataset.txt,
            delay,
            typewriteAll, elemArr.slice(1), delay
        );
    }
}

function typewrite(Elem, t, delay, func, arg1, arg2) {
    let txt = String(t);
    if(txt != ""){
        Elem.innerHTML += txt[0];
        setTimeout(() => {
            typewrite(
                Elem,
                txt.slice(1, txt.length),
                delay,
                //here:
                func,
                arg1,
                arg2
            )
        }, delay)
    } else {
        setTimeout(() => {
                Elem.setAttribute("typing", "end");
                func(arg1, arg2)
        }, 10 * delay)
    }
}
<div data-txt="Some text to type"></div>
<div data-txt="Some more text to type..."></div>

И если вы создаете эффекты пишущей машинки, я настоятельно рекомендую вам использовать setInterval и функции генератора ES6, поскольку они делают код много читается ... и помогает избежать таких ошибок:

function typewrite(element, text, delay){
  return new Promise((resolve, reject) => {
    const iterator = (function*() {
      try{
        for(const letter of text){
          element.textContent += letter
          yield
        }
        element.setAttribute("typing", "end");
        resolve()
      }catch(e){
        reject(e)
      }finally{
        clearTimeout(interval)
      }
    })()
    const interval = setInterval(() => iterator.next(), delay);
    iterator.next()
  })
}

function typewriteAll(elems, delay){
  return elems.reduce((acc,elem) => acc.then(() => typewrite(elem, elem.dataset.txt, delay)), Promise.resolve())
}

var txtElems = document.querySelectorAll("[data-txt]");
txtElems = Array.from(txtElems);
typewriteAll(txtElems, 70)
<div data-txt="Some text to type"></div>
<div data-txt="Some more text to type..."></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...