Нужно немного разъяснений по уроку JavaScript.(Функции конструктора) - PullRequest
2 голосов
/ 25 мая 2019

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

Все, что мне нужно, это пояснить, как именно работает функция оценки и далее. Откуда берутся ценности? Как складывается каждый раз, когда человек дает правильный ответ? Я в основном хочу понять, как этот код генерирует число для отображения на консоли каждый раз, когда пользователь вводит истинное значение в предупреждение. Прошу прощения, если я не понимаю четко, мне просто нужно понять, как работает код с function score() и далее. Я не мог за свою жизнь понять это. Откуда sc получает свои значения, и куда он тоже его передает и; а также; а также. Есть ли кто-нибудь, кто хочет дать мне макет того, как этот код сочетается друг с другом. Буду вечно благодарен.

(function() {
    function Question(question, answers, correct) {
        this.question = question;
        this.answers = answers;
        this.correct = correct;
    }

    Question.prototype.displayQuestion = function() {
        console.log(this.question);

        for (var i = 0; i < this.answers.length; i++) {
            console.log(i + ': ' + this.answers[i]);
        }
    }

    Question.prototype.checkAnswer = function(ans, callback) {
        var sc;

        if (ans === this.correct) {
            console.log('Correct answer!');
            sc = callback(true);
        } else {
            console.log('Wrong answer. Try again :)');
            sc = callback(false);
        }

        this.displayScore(sc);
    }

    Question.prototype.displayScore = function(score) {
        console.log('Your current score is: ' + score);
        console.log('------------------------------');
    }


    var q1 = new Question('Is JavaScript the coolest programming language in the world?',
                          ['Yes', 'No'],
                          0);

    var q2 = new Question('What is the name of this course\'s teacher?',
                          ['John', 'Micheal', 'Jonas'],
                          2);

    var q3 = new Question('What does best describe coding?',
                          ['Boring', 'Hard', 'Fun', 'Tediuos'],
                          2);

    var questions = [q1, q2, q3];

    function score() {
        var sc = 0;
        return function(correct) {
            if (correct) {
                sc++;
            }
            return sc;
        }
    }
    var keepScore = score();


    function nextQuestion() {

        var n = Math.floor(Math.random() * questions.length);
        questions[n].displayQuestion();

        var answer = prompt('Please select the correct answer.');

        if(answer !== 'exit') {
            questions[n].checkAnswer(parseInt(answer), keepScore);

            nextQuestion();
        }
    }

    nextQuestion();

})();

Ответы [ 4 ]

1 голос
/ 25 мая 2019

sc получает значение из-за закрытия.Когда вложенная функция, возвращаемая score() и оператором if if (correct), имеет значение true, оценка увеличивается.Ниже приведен общий фрагмент кода.

function score(){
  let sc = 0;
  return function(correct){
    if(correct){
      
      sc++; //this is the same variable is upper scope.
      console.log(sc)
    }
    return sc;
  }
}

let temp = score();

temp(true);
temp(true);

Таким образом, в приведенном выше фрагменте внешняя функция score вызывается только один раз и выполняет две функции:

  • инициализирует переменную sc0
  • функция возврата, в которой sc будет ссылаться на переменную sc, созданную в верхней области видимости.

Это используется только для предотвращения создания глобальныхпеременная

Рассмотрим еще один простой фрагмент.

let count = 0;

function counter(){
  count++;
  console.log(count)
}

counter();
counter();
counter();

В приведенном выше фрагменте родительская область действия является глобальной, а дочерняя область - областью действия.Теперь переменная count присутствует внутри counter() (даже если она не объявлена ​​внутри counter()) из-за закрытия.

  • Теперь в первом фрагменте функция score() имеет видточно так же, как глобальная область (во втором фрагменте),
  • В первом фрагменте возвращаемая функция return function(correct){...} аналогична вложенной функции counter() во втором фрагменте.
  • и sc переменнаяэто как переменная count.

Не могли бы вы просто объяснить prototype.checkAnswer немного больше

Этот метод принимает два аргумента.ans и callback.

Рассмотрим строку в функции nextQuestion()

questions[n].checkAnswer(parseInt(answer), keepScore);

Теперь, если вы заметили, что в функцию переданы два параметра.Один - это номер правильного ответа, а другой - обратный вызов (функция, которая передается другой функции, будет вызвана позже).

Мы передаем keepScore, который я объяснил выше, это функция, возвращаемая score()то есть function(correct){...}.Теперь эта функция вызывается внутри метода-прототипа.Этот обратный вызов возвращает значение sc, которое объявлено в его родительской функции score.И затем он отображается с помощью this.displayScore

Теперь, с чем вы, возможно, перепутали, это переменная sc в prototype.checkAnswer.Эта переменная просто для предотвращения двойной записи this.displayScore();

Функция может быть записана как:

Question.prototype.checkAnswer = function(ans, callback) {
    if (ans === this.correct) {
        console.log('Correct answer!');
        this.displayScore(callback(true));
    } else {
        console.log('Wrong answer. Try again :)');
        this.displayScore(callback(false));
    }        
}

Даже если мы объявим другую переменную sc в prototype.checkAnswer не имеет отношения к переменной sc внутри score().Это совершенно разные переменные, поскольку переменные, объявленные с помощью var, имеют область действия функции.

Создайте фрагмент кода:

function score(){
  var sc = 0;
  return function(){
    sc++;
    console.log(`I am sc of score: ${sc}`);
    return sc;
  }
}

let temp = score();

function wrapper(callback){
  var sc = 0;
  console.log(`I am sc of wrapper: ${sc}`);
  callback();
}

wrapper(temp)
wrapper(temp)
wrapper(temp)
wrapper(temp)
1 голос
/ 25 мая 2019

Немного хитрый момент для непосвященного: функция score возвращает функцию и использует замыкание .

function score() {
  var sc = 0;
  return function(correct) {
    if (correct) {
      sc++;
    }
    return sc;
  }
}

Эта строка:

var sc = 0;

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

// can't do this. sc gets recreated and reset on every call:
function score (correct) {
  var sc = 0;
  if (correct) {
    sc++
  }
  return sc;
}

Но вы также не хотите, чтобы переменная была доступна всем, поэтому вы тоже не хотите этого делать:

// don't want this either.
// score shouldn't be modifiable outside of our keepScore method.
let sc = 0;

function score (correct) {
  if (correct) {
    sc++;
  }
  return sc;
}

// this approach works, but now cheaters can set
// the score outside our scorekeeping function:
sc = 999999; // oh noes! hacks!

Так что мы можем сделать? Мы можем:

Первое: создайте переменную в области действия функции, где она защищена от внешних махинаций:

function score () {
  var sc = 0; // unavailable outside this function
}

Второе: создайте еще одну функцию внутри первого , которая может изменять переменную:

function score () {
  var sc = 0; // unavailable outside this function

  // a new function that has access to the outer function's sc variable.
  function(correct) {
    if (correct) {
      sc++;
    }
    return sc;
  }
}

Наконец, возвращение внутренней функции из score() дает сторонним лицам способ регистрировать правильные ответы, не раскрывая саму переменную счета:

function score () {
  var sc = 0; // unavailable outside this function

  // return this function to the caller and voila!
  // they now have a self-contained scorekeeper function.
  return function(correct) {
    if (correct) {
      sc++;
    }
    return sc;
  }
}

Так что теперь, когда вы делаете это:

var keepScore = score();

keepScore - это внутренняя функция с собственной внутренней переменной sc.

Если у вас была многопользовательская версия, вы можете получить ее для каждого игрока:

// each gets their own instance of
// that inner function with its own
// independent sc variable.
const playerOneScore = score();
const playerTwoScore = score();

playerOneScore(true); // 1
playerOneScore(true); // 2

playerTwoScore(false); // 0
playerTwoScore(true); // 1

Я думаю, что как только вы поймете это немного, все остальное будет иметь больше смысла.

1 голос
/ 25 мая 2019
  1. Это автоматически выполняемая функция-обертка.Он автоматически вызывает nextQuestion(), чтобы начать процесс
  2. var n = Math.floor(Math.random() * questions.length); выбирает случайный вопрос из списка questions
  3. displayQuestion() показывает информацию из второго параметра new Question() в качестве возможных ответов.Третий параметр - правильный ответ.
  4. Пользователь вводит свой ответ в prompt('Please select the correct answer.');, а если он не exit, то сравнивает ответ с правильным значением.
  5. После отображения кода ответа вызывает keepScore(correct) длядобавить счет к окончательному результату.
  6. [GOTO # 2] используя nextQuestion();
0 голосов
/ 25 мая 2019

Здесь функция оценки является закрытием

Состояние sc внутри оценки инициализируется, когда вызывается оценка.

var keepScore = score();

Теперь в keepScore есть функция, возвращаемая замыканием, равное

function (correct) {           
        if (correct) {
            sc++; // it has a "closure" over it
        }
        return sc;
    }

, которое принимает логическое значение.то есть keepScore (true) или keepScore (false)

Теперь эта функция keepScore передается для проверки ответа

questions[n].checkAnswer(parseInt(answer), keepScore);

В ответе на вопрос, если ответисправить это будет верно для keepScore

callback(true) <=> keepScore(true)

Если вы хотите получить больше ясности по закрытию, вы можете просмотреть эту статью

https://github.com/getify/You-Dont-Know-JS/blob/master/up%20%26%20going/ch2.md#closure

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...