2016-12-08 3 views
0

Другой вопрос JavaScript, который я нашел в Интернете, но я не мог понять, как это работает. Вопрос в основном спрашивает, что такое пароль. Пароль не зависит от внешних ресурсов и не изменяется со временем (не зависит от текущей даты или времени). Кроме того, в вопросе говорится, что есть ровно один правильный пароль. Я начинаю JavaScript, поэтому прошу прощения, если это простой вопрос об стандартном интервью. Это функция:JavaScript: Угадающий пароль

const checkPassword = a => { 
    if(a !== (a += '')) return false; 
    if(a !== (a = a.replace(/[^a-z]/g, ''))) return false; 
    a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]); 
    a = [...a].reverse().join([] + []); 

    try{ 
    Function('\'' + a + '\';++1..a')(); 
    return false; 
    }catch(a){ 
    return true; 
    } 
}; 

alert(checkPassword(prompt('Enter password:')) ? 'Correct password.' : 'Wrong. Try again.'); 

Сначала это было трудно не выглядеть слишком меня, потому что все открыто, так что я могу просто следовать код построчно и выяснить, как это работает. Хорошо, я понимаю, что в первой строке функции проверки они проверяют, является ли пароль строкой (почему? Это может быть что-то еще?). Затем, если я хорошо понял это регулярное выражение, они проверяют, состоит ли скрипт только в маленьких буквах алфавита (или я ошибаюсь?). Итак, на данный момент я знаю, что знаю, что он должен состоять только из букв. После этого они выполняют какое-то странное регулярное выражение, которое я не могу полностью понять. Мне кажется, что это регулярное выражение будет соответствовать цельной строке, так почему они присоединяются к ней?

Затем они меняют строку и соединяются пустым массивом (это то же самое, что и обычная реверсивная строка или что?). После этого в блоке try я не могу понять, что происходит? Что делает Function конструктор на самом деле здесь? В чем смысл ++1..a? Мне просто интересно, как подойти к таким вопросам, как этот?

+0

Подсказка: '({} + {}) [7]' - это один пробельный символ, потому что '{} + {}' создает * string * '" [object Object] [object Object] "'. – nnnnnn

+1

Попробуйте выполнить функцию с помощью отладчика или добавьте 'console.log (a)' после каждой строки. Эта строка с '.match()' выглядит так, как будто она обновляет 'a', чтобы вставить пробел после шестого символа ввода. – nnnnnn

+0

@ Bergi. Почему вы удалили тег ES6? Я не думаю, что '[... a]' будет компилироваться в более старых ecmascripts. –

ответ

2

Я буду прыгать прямо в ключевой строке:

Function('\'' + a + '\';++1..a')(); 

Он создает, а затем сразу же выполняет новую функцию с функцией органа, созданного из этого странного вида строки. Если переменная a есть, скажем, 'abcde' затем тело новой функции будет:

'\'' + 'abcde' + '\';++1..a' 

, который походит на наличие этой функции:

function() { 
    'abcde';++1..a 
} 

Или с некоторыми пробелами:

function() { 
    'abcde'; 
    ++1..a 
} 

Обратите внимание, что строка в первой строке динамически задается в зависимости от того, что находится в переменной a, но часть ++1..a - hardco Ded.

Теперь, отметив, что функция находится внутри try/catch() блока, если новая функция выполняется без ошибок, то checkPassword() вернется false, но если новая функция врезается checkPassword() возвращается true. Другими словами, ожидается, что поведение этой динамической функции изменится на сбой или не зависит от того, что находится в строке из переменной a.

Итак, какая строка сама по себе в первой строке функции может изменить поведение функции? Существует только одна возможность, и это (парить, чтобы показать спойлер):

'use strict' ... которые должны быть введены в качестве пароля 'tcirtsesu' из первых нескольких строк функция, выполняющая .match() и .reverse().

Имея это в виду, что это не на самом деле даже неважно, что ++1..a часть делает, но она в основном принимает .a свойство 1, которое undefined, и пытается увеличить его, что ...

- это ошибка в строгом режиме, но не в нестандартном режиме.

Для полноты очень краткое объяснение этих строк:

a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]); 
a = [...a].reverse().join([] + []); 

.match() функция возвращает массив. /^.{6}|.+/g соответствует первым шести символам, ИЛИ любому числу символов, что означает, что "abcdefghijkl".match(/^.{6}|.+/g) возвращает ["abcdef", "ghijkl"]. Тогда ({} + {})[7] в основном просто символ пробела, потому что {} + {} - это строка "[object Object][object Object]". Так что строка в основном вставляет пробел после шестого символа.

Линия .reverse() затем отменяет результат.

Смежные вопросы