Конструкция языка Javascript недостаточно строга, и если вы не будете осторожны, во многих местах могут возникнуть ошибки.
Например, рассмотрим следующую ситуацию.
Теперь нам нужно определить, существует ли глобальный объект myObj. Если он не существует, объявите его. Алгоритм, описанный на естественном языке, выглядит следующим образом:
Скопируйте код кода следующим образом:
если (myObj не существует){
объявить мойОбъект;
}
Вы можете подумать, что написать этот код легко. Но на самом деле связанные с этим грамматические проблемы гораздо сложнее, чем мы думаем. Юрий Зайцев отметил, что существует более 50 способов определить, существует ли Javascript-объект. Только если вы очень хорошо разбираетесь в деталях реализации языка Javascript, вы сможете заметить разницу между ними.
Первый способ письма
Интуитивно вы можете подумать, что можете написать:
Скопируйте код кода следующим образом:
если (!myObj) {
мойОбъект = {};
}
Однако при запуске этого кода браузер напрямую выдает ошибку ReferenceError, что приводит к прерыванию операции. В чем дело?
Кстати, когда оператор if определяет, является ли myObj пустым, переменная еще не существует, поэтому выдается сообщение об ошибке. Измените его на следующее, и он будет работать правильно.
Скопируйте код кода следующим образом:
если (!myObj) {
вар myObj = {};
}
Почему после добавления переменной нет ошибки? Может ли быть так, что в этом случае, когда оператор if выносит суждение, myObj уже существует?
Чтобы ответить на этот вопрос, вы должны знать, как работает интерпретатор Javascript. Язык Javascript работает по принципу «сначала анализ, запуск позже». Объявление переменной уже завершено во время анализа, поэтому приведенный выше код фактически эквивалентен:
Скопируйте код кода следующим образом:
вар myObj;
если (!myObj) {
вар myObj = {};
}
Следовательно, когда оператор if выносит суждение, myObj уже существует, поэтому об ошибках не сообщается. Это эффект «подъема» команды var. Интерпретатор Javascript только «продвигает» переменные, определенные командой var, и не работает с переменными, которые назначаются напрямую без использования команды var. Вот почему будет сообщено об ошибке, если var не добавлен.
Второй способ написания
Помимо команды var, есть еще одна перезапись, которая также позволяет получить правильные результаты:
Скопируйте код кода следующим образом:
если (!window.myObj) {
мойОбъект = {};
}
Окно — это объект верхнего уровня JavaScript, а все глобальные переменные — его свойства. Таким образом, определение того, является ли myobj пустым, эквивалентно определению того, имеет ли объект окна атрибут myobj, поэтому можно избежать ошибок ReferenceError, возникающих из-за того, что myObj не определен. Однако из стандартизации кода лучше всего добавить var во вторую строку:
Скопируйте код кода следующим образом:
если (!window.myObj) {
вар myObj = {};
}
Или написано так:
если (!window.myObj) {
window.myObj = { };
}
Третий способ письма
Недостатком описанного выше метода записи является то, что в некоторых работающих средах (например, V8, Rhino) окно может не быть объектом верхнего уровня. Итак, рассмотрите возможность переписать его как:
Скопируйте код кода следующим образом:
если (!this.myObj) {
this.myObj = { };
}
На уровне глобальных переменных это ключевое слово всегда указывает на переменную верхнего уровня, поэтому оно может быть независимым от различных исполняемых сред.
Четвертый способ письма
Однако приведенный выше способ записи менее читабелен, а указатель на него является переменным и подвержен ошибкам, поэтому перепишем его дальше:
Скопируйте код кода следующим образом:
вар глобальный = это;
если (!global.myObj) {
global.myObj = { };
}
Гораздо проще использовать пользовательскую переменную global для представления объекта верхнего уровня.
Пятый способ письма
Вы также можете использовать оператор typeof, чтобы определить, определен ли myObj.
Скопируйте код кода следующим образом:
if (typeof myObj == "не определено") {
вар myObj = {};
}
В настоящее время это наиболее широко используемый метод определения существования объекта JavaScript.
Шестой способ письма
Поскольку значение myObj напрямую равно undef, когда оно определено, но не присвоено, описанный выше метод записи можно упростить:
Скопируйте код кода следующим образом:
если (myObj == не определено) {
вар myObj = {};
}
Здесь следует отметить две вещи: во-первых, ключевое слово var во второй строке не может отсутствовать, иначе возникнет ошибка ReferenceError. Во-вторых, неопределенное значение нельзя добавлять с одинарными или двойными кавычками, поскольку здесь сравнивается тип данных неопределенного значения. не "неопределено" Эта строка.
Седьмой способ письма
Вышеупомянутый метод записи по-прежнему справедлив в случае «точного сравнения» (===):
Скопируйте код кода следующим образом:
если (myObj === не определено) {
вар myObj = {};
}
Восьмой способ письма
Согласно конструкции языка JavaScript, undefine == null, поэтому сравнение того, равен ли myObj нулю, также может дать правильный результат:
Скопируйте код кода следующим образом:
если (myObj == ноль) {
вар myObj = {};
}
Однако, хотя результаты прогона верны, с семантической точки зрения этот метод оценки неверен, и его следует избегать. Поскольку значение null относится к пустому объекту, которому присвоено значение null, то есть этот объект действительно имеет значение, а значение undefine относится к объекту, который не существует или которому не присвоено значение. Поэтому здесь можно использовать только «оператор сравнения» (==). Если здесь используется «оператор точного сравнения» (===), произойдет ошибка.
Девятый способ письма
Вы также можете использовать оператор in, чтобы определить, является ли myObj атрибутом объекта верхнего уровня:
Скопируйте код кода следующим образом:
if (!('myObj' в окне)) {
window.myObj = { };
}
Десятый способ письма
Наконец, используйте метод hasOwnProperty, чтобы определить, является ли myObj свойством объекта верхнего уровня:
Скопируйте код кода следующим образом:
if (!this.hasOwnProperty('myObj')) {
this.myObj = { };
}
Подвести итог
1. Если вы только определяете, существует ли объект, рекомендуется использовать пятый способ записи.
2. Если помимо существования объекта необходимо еще определить, имеет ли объект нулевое значение, рекомендуется использовать первый способ записи.
3. Если нет особых обстоятельств, все переменные следует объявлять с помощью команды var.
4. Чтобы обеспечить кроссплатформенность, рекомендуется избегать использования окна для представления объектов верхнего уровня.
5. В языке Javascript значения null и undef легко перепутать. В случаях, когда могут быть задействованы оба параметра, рекомендуется использовать оператор «точного сравнения» (===).