需要对JavaScript课程进行一些澄清。 (构造函数)

时间:2019-05-25 07:29:18

标签: javascript function class

我有以下代码需要澄清。在继续之前,我想完全理解它。我知道该示例可能很愚蠢,并且我相信有很多更好的方法可以解决该问题,但是出于本课的目的,此人使用了该示例。

我需要做的只是澄清得分函数的流程是如何工作以及向前。价值从何而来?人每次给出正确答案时,它是如何累加的? 我基本上想了解每次用户向警报中输入真实值时,此代码如何生成数字以显示在控制台上。很抱歉,如果我不清楚的话,我只需要了解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 个答案:

答案 0 :(得分:1)

  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();

答案 1 :(得分:1)

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仅被调用一次,并执行以下两项操作:

  • 初始化变量sc,即0
  • 返回函数,其中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

此方法带有两个参数。 anscallback

考虑函数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)

答案 2 :(得分:1)

这里的未初始化项有些棘手,是score函数返回一个函数,并使用了closure

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

我认为,一旦您了解了这一点,其余的内容就会更加有意义。

答案 3 :(得分:0)

这里的得分函数是闭包

调用分数时,将初始化分数内部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);

在检查中,如果答案正确,则将true传递给keepScore

callback(true) <=> keepScore(true)

如果您想更清楚地了解Closure,可以阅读这篇文章

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