Что бы я делал, это игнорировать формат и проверять числовое содержимое:
var originalPhoneNumber = "415-555-1212";
function isValid(p) {
var phoneRe = /^[2-9]\d{2}[2-9]\d{2}\d{4}$/;
var digits = p.replace(/\D/g, "");
return phoneRe.test(digits);
}
Я нашел отчет о выпуске v8 , который именно о том, что вы просите.
Теперь, чтобы суммировать то, что сказано в этом выпуске ... v8 может хранить переменные, которые являются локальными для функции в стеке или в объекте «context», который живет в куче. Он будет выделять локальные переменные в стеке, пока функция не содержит никакой внутренней функции, которая относится к ним. Это оптимизация. Если любая внутренняя функция ссылается на локальную переменную, эта переменная будет помещена в объект контекста (т. Е. В куче, а не в стеке). Случай eval
является особенным: если он вообще вызван внутренней функцией, все локальные переменные помещаются в объект контекста.
Причина для контекстного объекта заключается в том, что в общем случае вы можете вернуть внутреннюю функцию из внешней, а затем стек, который существовал во время выполнения внешней функции, больше не будет доступен. Таким образом, все, что имеет доступ к внутренней функции, должно пережить внешнюю функцию и жить в куче, а не в стеке.
Отладчик не может проверить те переменные, которые находятся в стеке. Что касается проблемы, возникающей при отладке, один из участников проекта говорит, что :
Единственное решение, о котором я мог думать, это то, что всякий раз, когда devtools включен, мы уничтожаем весь код и перекомпилируем с принудительным контекстным распределением. Это резко изменило бы производительность при использовании devtools.
blockquote>Вот пример «если какая-либо внутренняя функция относится к переменной, поместите ее в объект контекста». Если вы запустите это, вы сможете получить доступ к
x
в инструкцииdebugger
, хотяx
используется только в функцииfoo
, , которая никогда не называется !function baz() { var x = "x value"; var z = "z value"; function foo () { console.log(x); } function bar() { debugger; }; bar(); } baz();
Я также заметил это в nodejs. Я полагаю (и я допускаю, что это только предположение), что при компиляции кода, если x
не появляется внутри bar
, он не делает x
доступным в области bar
. Это, вероятно, делает его несколько более эффективным; проблема заключается в том, что кто-то забыл (или не заботился), что даже если в bar
нет x
, вы можете решить запустить отладчик и, следовательно, по-прежнему необходимо получить доступ к x
изнутри bar
.
eval
. Если переменная объявлена, она должна быть доступна.
– David Knipe
22 April 2017 в 11:30
Ничего себе, действительно интересно!
Как уже упоминалось, это, по-видимому, связано с scope
, но более конкретно, связано с debugger scope
. Когда внедренный скрипт оценивается в инструментах разработчика, он, как представляется, определяет ScopeChain
, что приводит к некоторой причудливости (поскольку оно связано с областью инспектора / отладчика). Вариант того, что вы разместили, это:
(EDIT - на самом деле, вы упомянули об этом в своем исходном вопросе, yikes, мой плохой! )
function foo() {
var x = "bat";
var y = "man";
function bar() {
console.log(x); // logs "bat"
debugger; // Attempting to access "y" throws the following
// Uncaught ReferenceError: y is not defined
// However, x is available in the scopeChain. Weird!
}
bar();
}
foo();
Для амбициозного и / или любопытного масштаба (heh) из источника, чтобы узнать, что происходит:
https://github.com/WebKit/webkit/tree/master/Source / JavaScriptCore / inspector https://github.com/WebKit/webkit/tree/master/Source/JavaScriptCore/debugger
Я подозреваю, что это связано с перестановкой переменных и функций. JavaScript приносит все объявления переменных и функций в начало функции, в которой они определены. Дополнительная информация здесь: http://jamesallardice.com/explaining-function-and-variable-hoisting-in-javascript/
Бьюсь об заклад, что Chrome вызывает точку прерывания с переменной, недоступной для области видимости, потому что в функции больше ничего нет. Это работает:
function baz() {
var x = "foo";
function bar() {
console.log(x);
debugger;
};
bar();
}
Как это делает:
function baz() {
var x = "foo";
function bar() {
debugger;
console.log(x);
};
bar();
}
Надеюсь, что и / или ссылка выше помогает. Это мой любимый вид вопросов SO, BTW:)
Как @Louis сказал, что это вызвано оптимизациями v8. Вы можете перемещать стек вызовов в кадр, где эта переменная видна:
Или заменить debugger
на
eval('debugger');
eval
отключит текущий кусок
debugger
, и контекст действительно доступен. Если вы повышаете стек на один уровень до кода, который вы пытаетесь отлаживать, вы снова не имеете доступа к контексту. Так что это просто немного неуклюже, не имея возможности смотреть на код, который вы отлаживаете, при доступе к скрытым переменным закрытия. Тем не менее, я буду поддерживать, поскольку это избавляет меня от необходимости добавлять код, который явно не предназначен для отладки, и он дает мне доступ ко всему контексту без деоптимизации всего приложения.
– Sigfried
27 July 2017 в 11:12
eval
ed source, чтобы получить доступ к контексту: вы не можете пройти через код (если вы не поместите eval('debugger')
между всеми строками, которые вы хотите пройти).
– Sigfried
27 July 2017 в 12:46