Объясните процесс кода JavaScript на простом английском языке

#javascript #reactjs

Вопрос:

Я учусь на Udacity, и у них есть тест, который я сам не смог пройти. Я решил взглянуть на предоставленное решение, но мне нужно понять процесс написания кода (я кое-что понимаю). Вот он:

 // creates a line of * for a given length
function makeLine(length) {
    var line = "";
    for (var j = 1; j <= length; j  ) {
        line  = "* ";
    }
    return line   "n";
}

// your code goes here.  Make sure you call makeLine() in your own code.
function buildTriangle(length) {
    // Let's build a huge string equivalent to the triangle
    var triangle = "";

    //Let's start from the topmost line
    var lineNumber = 1;

    for(lineNumber=1; lineNumber<=length; lineNumber  ){
        // We will not print one line at a time.
        // Rather, we will make a huge string that will comprise the whole triangle
        triangle = triangle   makeLine(lineNumber);
    }
    return triangle;
}

// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string 
// because the console.log() accepts a string argument
console.log(buildTriangle(10)); 

Я понимаю, что makeLine() создаст строку звездочек на основе значения длины, которое передается ей при вызове внутри buildTriangle()

Но я не понимаю, как работает эта линия:

 triangle = triangle   makeLine(lineNumber);
 

Разве это не работает так, как строка в makeLine (), которая

 line  = "* ";
 

В чем разница между использованием = и triangle = triangle makeLine(lineNumber) ? Если они работают одинаково, то вывод должен быть неправильным.

Также, пожалуйста, поправьте меня, если я ошибаюсь в своем понимании переменной длины в makeLine(длина) и buildTriangle (длина). Являются ли они разными переменными из-за разной области видимости? Могу ли я изменить имя переменной в функции buildTriangle на что-то вроде buildTriangle (passedValueToMakeLineFunc)?

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

Комментарии:

1. Быстрый ответ: Попробуйте отредактировать код, чтобы он был triangle = makeLine(lineNumber); . Вы должны заметить, что результат такой же, как и при использовании triangle = triangle makeLine(lineNumber); !

2. «Являются ли они разными переменными из — за разной области видимости?» — да, это правильно, вы можете изменить имя переменной на любое другое допустимое имя переменной

3. Хорошо, Джон Кугельман, понял. Tq 🙂 @DemiPixel да, работал так же. но я все еще в замешательстве. Первый цикл в функции buildTriangle вызывает функцию makeLine, которая вернет первую строку звездочки «* » с новой строкой «n «, поэтому во втором цикле переданное значение в функцию makeLine() увеличивается на 1, поэтому она вернет 2 звездочки»**», но так как мы использовали =, 2 звездочки будут добавлены к первой «* » из первого цикла и вернут 3 звездочки вместо 2 для второй строки. Я думаю, что мне нужно больше объяснений того, как работает = или как каждый цикл цикла связан с предыдущим раундом.

Ответ №1:

в чем разница между использованием = и треугольником = треугольник линия(номер строки)

Они эквивалентны:

 triangle = triangle   makeLine(lineNumber);
 
 triangle  = makeLine(lineNumber);
 

…переменная длина в makeLine(длина) и buildTriangle (длина) … являются ли они разными переменными…

Правильный.

  1. Переменные полностью независимы и
  2. вы можете называть их как хотите.

шаг за шагом на простом английском языке

Приносим извинения, если это слишком многословно или не то, что вы имели в виду:

  • объявляйте функции makeLine и buildTriangle (определяйте, но не выполняйте)
  • вызовите buildTriangle с помощью одного аргумента ( 10 ), чтобы разрешить значение, которое будет передано console.log

Выполнение buildTriangle:

 function buildTriangle(length) {
    // Let's build a huge string equivalent to the triangle
    var triangle = "";

    //Let's start from the topmost line
    var lineNumber = 1;

    for(lineNumber=1; lineNumber<=length; lineNumber  ){
        // We will not print one line at a time.
        // Rather, we will make a huge string that will comprise the whole triangle
        triangle = triangle   makeLine(lineNumber);
    }
    return triangle;
}
 
  • начните выполнение buildTriangle с length = 10
  • объявите переменную, вызываемую triangle с начальным пустым строковым значением
  • объявите переменную, вызываемую lineNumber с начальным значением 1 .
  • for цикл инициализации: установите переменную lineNumber в 1 (снова)
  • оцените for состояние цикла. lineNumber меньше или равно length (10)?
  • Номер строки равен 1, что меньше 10, поэтому условие цикла верно. выполните тело цикла.
  • оценить makeLine(1) (номер строки равен 1)

Выполнение makeLine:

 function makeLine(length) {
    var line = "";
    for (var j = 1; j <= length; j  ) {
        line  = "* ";
    }
    return line   "n";
}
 
  • начните выполнение makeLine с length = 1
  • объявите вызываемую переменную line и инициализируйте ее в пустую строку
  • for цикл начала: объявить и инициализировать переменную j с начальным значением 1
  • оцените for состояние цикла. j меньше или равно length (1)?
  • j равно 1, что равно 1, поэтому условие цикла верно. выполните тело цикла.
  • добавить "* " к line . ( line сейчас "* " )
  • прирост j . j это сейчас 2 .
  • оцените for состояние цикла. j меньше или равно length (1)?
  • j является 2 . условие ложно. выходная петля.
  • возвращаемое line значение с добавлением новой строки: ( "* n" )

(Возобновить buildTriangle выполнение)

  • установите triangle его текущее значение (пустая строка) плюс разрешенное makeLine значение: triangle теперь "* n"
  • конец тела петли. выполните выражение после цикла (номер строки )
  • установлено lineNumber значение 2
  • оцените for состояние цикла. lineNumber меньше или равно length (10)?
  • lineNumber есть 2 , что меньше , чем 10 , поэтому условие цикла верно. выполните тело цикла.
  • оценить makeLine(2) (номер строки равен 2)

Выполнение makeLine:

  • начните выполнение makeLine с length = 2
  • объявите вызываемую переменную line и инициализируйте ее в пустую строку
  • for цикл начала: объявить и инициализировать переменную j с начальным значением 1
  • оцените for состояние цикла. j меньше или равно length (2)?
  • j равно 1, что меньше 2, поэтому условие цикла верно. выполните тело цикла.
  • добавить "* " к line . ( line сейчас "* " )
  • прирост j . j это сейчас 2 .
  • оцените for состояние цикла. j меньше или равно length (2)?
  • j равно 2, что равно 2, поэтому условие цикла верно. выполните тело цикла.
  • добавить "* " к line . ( line сейчас "* * " )
  • прирост j . j это сейчас 3 .
  • оцените for состояние цикла. j меньше или равно length (2)?
  • j является 3 . условие ложно. выходная петля.
  • возвращаемое line значение с добавлением новой строки: ( "* * n" )

(Возобновить buildTriangle выполнение)

  • установите triangle его текущее значение "* n" плюс разрешенное makeLine значение: triangle теперь "* n* * n"
  • конец тела петли. выполните выражение после цикла (номер строки )
  • установлено lineNumber значение 3
  • оцените for состояние цикла. lineNumber меньше или равно length (10)?
  • lineNumber есть 3 , что меньше , чем 10 , поэтому условие цикла верно. выполните тело цикла.
  • оценить makeLine(3) (номер строки равен 3)

Повторяйте описанные выше шаги, пока номер строки не достигнет 11 и цикл не завершится.

  • верните значение triangle вызывающему абоненту и выйдите buildTriangle . На данный момент значение triangle равно:
 * 
* * 
* * * 
* * * * 
* * * * * 
* * * * * * 
* * * * * * * 
* * * * * * * * 
* * * * * * * * * 
* * * * * * * * * * 
 
  • вызовите console.log со значением, возвращенным buildTriangle .
  • выход

Ваш пример приведен здесь для справки:

 // creates a line of * for a given length
function makeLine(length) {
    var line = "";
    for (var j = 1; j <= length; j  ) {
        line  = "* ";
    }
    return line   "n";
}

// your code goes here.  Make sure you call makeLine() in your own code.
function buildTriangle(length) {
    // Let's build a huge string equivalent to the triangle
    var triangle = "";

    //Let's start from the topmost line
    var lineNumber = 1;

    for(lineNumber=1; lineNumber<=length; lineNumber  ){
        // We will not print one line at a time.
        // Rather, we will make a huge string that will comprise the whole triangle
        triangle = triangle   makeLine(lineNumber);
    }
    return triangle;
}

// test your code by uncommenting the following line
// Note that the function buildTriangle() must return a string 
// because the console.log() accepts a string argument
console.log(buildTriangle(10));
 

Комментарии:

1. Просто наткнулся на этот вопрос во время случайного изучения. Я не прочитал весь вопрос и ответ, но я все равно благодарен @ray-hatfield за то, что вы нашли время, чтобы опубликовать ответ. 👏

Ответ №2:

Оператор присваивания сложения ( =)

someVar = "someString" это то же самое, что someVar = someVar "someString"

Продолжайте и замените свой пример на triangle = makeLine(lineNumber) , и вы увидите, что получите тот же треугольник.

2 с length

В этом случае они оба являются параметрами функций makeLine и buildTriangle .

  • Параметры функции ограничены областью действия функционального блока, что означает, что они доступны только внутри функции, недоступны снаружи.
  • Называйте их как хотите, это не имеет никакого эффекта за пределами функционального блока.
  • Обратите внимание, что если бы параметр длины действительно существовал вне объявлений функций, параметр длины закрывал бы/скрывал внешнюю переменную от использования внутри функции.
 var length = 4;
console.log("outer", length); // 4
function someFunction(length) {
  console.log("inner", length); // 5
}
someFunction(5);
console.log("outer", length); // 4
 

Код на английском языке

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

  1. makeLine Функция объявлена (но еще не запущена)
  2. buildTriangle Функция объявлена (но еще не запущена)
  3. Мы нажимаем console.log() с параметром вызова функции (buildTriangle(10)). Мы выполним эту функцию, и ее результат будет передан вызову функции журнала.
  4. Мы вошли в buildTriangle функцию с длиной параметра, равной 10.
  5. Мы создаем triangle переменную, в которую мы построим весь треугольник, новые строки и все остальное, инициализированные пустой строкой.
  6. Мы объявляем переменную lineNumber равной 1.
    • Этот просто для того, чтобы поссориться с тобой
    • Это не нужно было делать перед циклом for, было бы то же самое, чтобы for (var lineNumber=1; lineNumber<=length; lineNumber ){ ... } и не объявлять об этом раньше времени.
    • Не имеет значения, для чего он был инициализирован или не был инициализирован, поскольку цикл for устанавливает значение 1 при запуске.
  7. Мы попали в петлю for, for(lineNumber=1; lineNumber<=length; lineNumber )
    • Мы установили lineNumber значение 1
    • Мы продолжим выполнять еще одну итерацию этого цикла, пока lineNumber не будет
    • По завершении каждой итерации, перед проверкой условия продолжения, мы увеличим значение lineNumber на 1 ( lineNumber ).
  8. Для каждой итерации цикла (значения номеров строк 1,2,3,4,5,6,7,8,9,10) мы выполняем triangle = triangle makeLine(lineNumber); , который просто берет текущую triangle строку, добавляет makeLine(lineNumber) к ней результат и присваивает это значение triangle .
  9. Мы вошли в makeLine функцию с длиной параметра, равной 1.
    • Обратите внимание, что на данный момент единственной переменной, доступной для нашей области видимости, является length параметр. (Помимо 2 функций, я полагаю)
  10. Мы инициализируем новую переменную line в пустую строку.
    • Обратите внимание, что это будет совершенно новая / отдельная переменная строки для каждого выполнения этой функции Звучит так, как будто вы, возможно, повесили трубку?
    • Поскольку line переменная объявлена внутри функции, область ее действия находится там и недоступна снаружи или во время выполнения функции.
    • Это было бы по-другому, если бы оно было объявлено вне функции и не сбрасывалось в начале. Тогда каждое выполнение продолжало бы просто добавляться.
  11. Мы сталкиваемся с другим циклом for, на этот раз с переменной итератора, объявленной внутри (j) for (var j = 1; j <= length; j ) { ... }
    • Мы объявляем и инициализируем j значение 1
    • Мы продолжим выполнять еще одну итерацию этого цикла, пока j не будет
    • По завершении каждой итерации, перед проверкой условия продолжения, мы увеличим значение j на 1 ( j ).
  12. Для каждой выполняемой нами итерации цикла line = "* "; , которая просто берет текущую line строку, добавляет «* » и присваивает это значение line .
  13. После этого цикла мы сталкиваемся с оператором return, который является результатом объединения нашей строки построения с символом новой строки («n»).
  14. Предполагая, что мы прошли все наши buildTriangle итерации цикла for, мы сталкиваемся с нашим оператором return и возвращаем сборку triangle .
  15. Теперь мы указали возвращаемое значение, которое будет указано в качестве параметра console.log.
  16. Выполнено.