JavaScript: Переменные и константы. Константы и ссылочные типы

Когда в программе необходимо сохранить значение, чтобы использовать его позже, это значение присваивается переменной. Переменная – это просто символьное имя для значения, которое обеспечивает возможность получить значение по имени, то есть, когда в программе указывается имя переменной вместо неё подставляется значение.

Переменная получила своё название благодаря тому, что её значение может быть изменено по ходу выполнения программы.

Константы

Константа – это просто символьное имя для значения. Константа даёт возможность обратиться к значению по имени, это означает, что, когда в программе указывается имя константы, вместо неё подставляется значение. Константы используются для хранения данных, которые не должны изменяться во время выполнения программы.

Прежде чем использовать константу, её необходимо объявить. Константы объявляются с помощью ключевого слова const , за которым следует имя константы. Чтобы в коде программы отличать константы от переменных, константам условились давать имена написанные заглавными буквами:

Const MAX = 10;

После того как константа создана, попытка переопределить её на переменную или попытка присвоить существующей константе значение вызовет ошибку.

Зачем нужны переменные и константы

Переменные и константы помогают сделать программный код понятнее. Рассмотрим небольшой пример:

TotalPrice = 2.42 + 4.33; // Общая цена

Имеющиеся здесь числа могут означать что угодно. Чтобы стало понятно, что именно здесь суммируется, значение 2.42 можно присвоить переменной (или константе) candyPrice (цена конфет), а 4.33 - переменной (или константе) oilPrice (цена масла):

TotalPrice = candyPrice + oilPrice;

Теперь вместо того, чтобы вспоминать, что эти значения означают, можно увидеть, что в сценарии складывается цена конфет с ценой масла.

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

Область видимости констант

К константам применяются те же правила, что и к переменным, объявленным с помощью ключевого слова let:

Const MAX = 5; // Глобальная константа { const MAX = 10; // Блочная константа console.log(MAX); // 10 } console.log(MAX); // 5 foo(); // 15 console.log(MAX); // 5 function foo() { const MAX = 15; // Локальная константа console.log(MAX); }

Константы и ссылочные типы

Когда константе присваивается значение ссылочного типа, то неизменяемой становится ссылка на значение, а само значение остаётся доступным для изменений:

Const obj = {a: 5}; obj.a = 10; console.log(obj.a); // 10

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

Долгосрочная ценность программного обеспечения, находится в прямой зависимости от качества кода. За время своего существования, программа проходит через огромное множество рук и глаз разработчиков. Если программный код написан так, что может четко передавать свою структуру, характеристики, то вероятность его сломать снижается, в случае если в него будут вноситься в правки другими разработчиками или самим автором через длительный срок времени.

Соглашения о программном коде, может помочь в повышении качества выходной продукции, и снижает вероятность выхода ее из строя.

JavaScript файлы

Программы на JavaScript должны храниться в.js - файлах.

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

тэги должны быть размещены по возможности в конце документа. Это уменьшает задержки при загрузки html страницы.

Отступы

Отступы должны состоять из четырех пробелов. Поэтому для написания кода, нужно настроить свой редактор, чтобы табуляция содержала именно такое количество. Использование такого количества символов может повлиять на размер файла, но эта проблема решается путем сжатия файла перед запуском продукта в использование.

Длинна строки

Избегайте строки длинной более 80 символов. Если оператор не помещается на одной строке, то его необходимо перенести или разбить. При разбивании строки, следующая строка должна быть с отступом в 8 пробелов от начала.

В отступлении от соглашения, учитывая современные мониторы и разрешения, длину строки можно увеличить до 120 символов. Современные редакторы кода, делают подсветку этой линии, к примеру NetBeans, PHPStorm, и ее длину можно настраивать.

Комментарии

Необходимо стараться в полной мере давать описания сложным участкам кода. Разработчики, которые будут смотреть на ваш код, или вы сами через некоторое время должны понимать, что этот код делает. Комментарии должны быть хорошо написаны, ясно, корректно, если комментарий недостаточно полный, а еще хуже - ошибочный, который может ввести разработчика в заблуждение, в таком случае лучше не писать комментарий вообще.

Так же комментарии не должны описывать очевидные вещи, иначе они будут только тратить время читателя.

i = 0; // Set i to zero.

Еще одним из полезных свойств комментариев, что при написании их в определенных правилах, например JSDoc, они могут использоваться для генерирования документации программного кода.

Объявление переменных

Все переменные должны быть объявлены перед их использованием. JavaScript не требует таких конструкций, но при этом программу намного легче читать и это дает возможность легче обнаруживать не объявленные переменные, которые могут подразумеваться интерпретатором как глобальные. Предполагаемые, неявные глобальные переменные никогда не должны использоваться, все переменные должны объявляться только явным способом, и использованием оператора var.

Конструкция var должна идти первой в теле функции.

Предпочтительно, что бы каждая переменная была описана на новой строке и могла добавляться комментарием. По возможности лучше держать объявление переменных в алфавитном порядке.

Var currentEntry, // currently selected table entry level, // indentation level size; // size of table

В JavaScript нет блока объявления переменных, как к примеру это присутствует в таких языках как pascal, но для того чтобы соблюдать порядок в коде, лучше объявлять переменные в начале функции.

Использование глобальных переменных, должны быть сведены к минимуму, а неявное объявление глобальных переменных вообще не должны использоваться.

Объявление функций

Все функции должны быть объявлены до их использования. Внутренние функции могут объявляется через var. Это помогает прояснить, какие переменные включены в области функции.

Не должно быть пробела между именем функции и открывающейся скобкой списка параметров. Пробел должен быть между закрывающейся скобкой и фигурной скобкой тела функции. Само тело функции должно быть с отступом в четыре пробела. Правая фигурная скобка самой функции, должна быть выровнена по линии содержащей объявление функции.

Function outer(c, d) { var e = c * d; function inner(a, b) { return (e * a) + b; } return inner(0, 1); }

Если функция-литерал является анонимной, то должен быть пробел между словом function и открывающейся скобкой списка параметров. Если пробел отсутствует, то могут возникать путаницы, что наименование функции является function, что может показаться ошибкой при чтении кода.

Div.onclick = function (e) { return false; }; that = { method: function () { return this.datum; }, datum: 0 };

Использование глобальных функций, так же должно быть сведено к минимуму.

Когда функция должна быть вызвана немедленно, она заключается в круглые скобки. Результат работы такой функции будет тем, что эта функция возвращает, но не ссылка на саму функцию.

Var collection = (function () { var keys = , values = ; return { get: function (key) { var at = keys.indexOf(key); if (at >= 0) { return values; } }, set: function (key, value) { var at = keys.indexOf(key); if (at = 0) { keys.splice(at, 1); values.splice(at, 1); } } }; }());

Имена

Имена переменных или функций могут быть составлены из 26 больших и маленьких символов (A .. Z, a … z), 10 разрядов цифр (0 .. 9) и символа подчеркивания. Лучше избегать использования международных символов, потому что их чтение и понимание может внести определенные затруднения. Не используйте знак $ (знак доллара) или (обратную косую черту) в именах переменных и функций.

Не используйте символ подчеркивания _ в качестве первого символа имени. Этот способ иногда используется для обозначения локальных (приватных) переменных или функций, но на самом деле не обеспечивает этим переменным приватности. Если в вашем коде необходимо использования приватные члены, то нужно избегать возможности открытия этих данных.

Большинство переменных и функций должны начинаться с маленькой буквы.

Функции конструкторы, которые для работы используют оператор new должны начинаться с большой буквы. Во время компиляции JavaScript сценария, или проверки кода сторонними инструментами будут показывать предупреждения, если функции или имена переменных будут использоваться без конструкции new . Работа функции-конструктора которая не использует оператор new будет вести себя абсолютно иначе, по этому, соглашение о написании таких функций с большой буквы является в некоторой степени защитой от ошибки.

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

Операторы Простые операторы

Каждая строка должна содержать не более одного оператора. Каждый простой оператор должен заканчиваться точкой с запятой (;). Обратите внимание, что оператор присваивания, которому присваивается функция, литерал, должны заканчиваться точкой с запятой.

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

Составные операторы

Составные операторы - это операторы которые содержать в себе списки других операторов, заключенных в {} (фигурные скобки).

  • Операторы внутри составных операторов должны иметь отступ в четыре пробела.
  • {(Левая фигурная скобка) должна быть в конце строки, в которой начинается составной оператор.
  • } (Правая фигурная скобка) следует ставить на новую строку и с отступом, для выравнивания с началом строки, содержащей соответствующую {(левая фигурная скобка).
  • Фигурные скобки должны присутствовать всюду где возможно их присутствие, это необходимо для избежания случайных ошибок, и для удобства чтения кода.
Метки

Наличие меток break и continue в коде может быть использованы только в конструкциях while , for , do и switch .

Оператор return

Значение оператора return никогда не должно заключаться в () (скобки). Значение этого оператора должно начинаться на той же строке что и сам оператор return, что бы избежать случайной вставки точки с запятой при интерпретации или сжатии кода.

Оператор if

Конструкция if должна иметь следующий вид:

If (condition) { statements } if (condition) { statements } else { statements } if (condition) { statements } else if (condition) { statements } else { statements }

Оператор for

Оператор for должен иметь следующую конструкцию:

For (initialization; condition; update) { statements } for (variable in object) { if (filter) { statements } }

Первая форма записи служит для работы с массивами и циклами с заданным числом итераций.

Вторая форма используется в случае работы с объектами. Нужно иметь в виду, что члены которые добавляются к прототипу объекта, буду включаться в перечисление. Для этого нужно использовать проверку с помощью метода hasOwnProperty, что бы отличить истинные свойства объекта:

For (variable in object) { if (object.hasOwnProperty(variable)) { statements } }

Оператор while

Конструкция while должна выглядеть следующим образом:

While (condition) { statements }

Оператор do

Оператор do должен выглядеть следующим образом:

Do { statements } while (condition);

В отличии от других заявленных составных операторов, этот всегда должен заканчиваться; (точкой с запятой).

Оператор switch

Оператор switch должен выглядеть следующим образом:

Switch (expression) { case expression: statements default: statements }

Каждая ветка case должна быть на одной линии с оператором switch. Это позволяет избегать чрезмерных отступов.

Каждая группа операторов case, кроме default должна заканчиваться break , return или throw .

Оператор try

Оператор try должен выглядеть следующим образом:

Try { statements } catch (variable) { statements } try { statements } catch (variable) { statements } finally { statements }

Оператор continue

Избегайте использования оператора continue. Этот оператор имеет тенденцию скрывать поток выполнения функции.

Оператор with

With оператор не должен использоваться.

Пробелы

Пустые строки улучшают читабельность путем разделения кода на секции которые логически связанные между собой.

Пробелы должны использоваться в следующих случаях:

  • Ключевое слово с последующей ((левая скобка) должны быть разделены пробелом
    while (true) {
  • Пробел не должен ставиться между именем функции и ((левой скобкой), в конструкции function f(). Это помогает различать ключевые слова и вызов функции.
  • Все двоичные операторы, кроме. (точки), ((левой скобки) и [ (левой квадратной скобки) должны быть разделены пробелом.
  • Каждая; (точка с запятой) в контрольной части конструкции for должна быть разделена пробелом.
  • Пробелы должны следовать после каждой запятой.

В больших проектах становится очень сложно учитывать все эти соглашения без использования вспомогательных инструментов, и редакторов кода. По этому, для собственного контроля, есть необходимость обзавестисьтакими инструментами.

JSLint. Инструмент для проверка JavaScript кода

Язык JavaScript это интерпретируемый язык, который не имеет своего компилятора, по сравнению с такими языками как Java, C++, который бы при сборке проекта или перед запуском проверял бы качество написанного кода, учитывая различные нюансы, такие как объявленные но неиспользуемые переменные, не оптимизированные участки кода, пропущенные точки с запятой, и т.д. По этому было бы полезно иметь инструмент, который бы выполнял проверку и указывал разработчику на различные погрешности.

Одним из таких инструментом и есть JSLint. JSLint - это программа написанная на JavaScript, назначение которой заключается в поиске проблем в программах JavaScript.

Когда C был еще молодым языком, было несколько распространенных ошибок программирования, которые не отлавливались примитивными компиляторами, так, была разработана программа под названием lint, что бы сканировать исходный файл для поиска ошибок.

Когда язык дошел до определенного уровня совершенства, компиляторы стали лучше его проверять и выдавать соответствующие сообщения после чего, программа lint стала не нужна.

JavaScript является молодым языком. Первоначально он использовался для выполнения небольших задач в веб-страницах, задач, для которых Java был слишком тяжелым и неуклюжим. В настоящее время, язык JavaScript играет большую роль в веб, и используется в больших и сложных проектах. Многие из функций, которые были реализованы в языке, были направлены на то, что бы сделать его простым, но когда проекты становятся больше и сложнее, то появляется повод для беспокойства из за такой функционала. По этому программы на JavaScript нуждаются в таком инструменте как lint .

JSLint берет исходный код JavaScript и сканирует его. При нахождении проблемы, возвращается сообщение с ее описанием, и приблизительное ее месторасположение в исходном файле. Проблема не обязательно может быть ошибкой синтаксиса, так же проводится проверки стиля, соблюдение структуры кода.

Глобальные переменные

Самая большая проблема в JavaScript - это зависимость от глобальных переменных которые были объявлены неявно. Если переменная не объявлена с помощью конструкции var, то в JavaScript эта переменная становится глобальной, как свойство объекта window . Из за этого могут возникать различного рода ошибки.

JSLint требует, что бы все переменные и функции были объявлены до их использования или вызова. Это позволяет без проблем обнаруживать глобальные переменные, а так же является хорошим тоном, и дает возможность легче читать исходный код программы.

Иногда файл зависит от глобальных переменных и функций, которые определены в другом месте. Для этого необходимо такие переменные описать в специальной директиве /*global */, которая указывать JSLint что они используются в других файлах и не являются ошибочными. Переменные в директиве представляют собой список имен разделенные запятыми. Каждое имя может включать двоеточие, после которого устанавливается флаг true или false, что указывает, была ли переменная предназначена для этого файла, или нет.

Некоторые глобальные переменные уже могут быть определены изначально. Предположим, браузер, когда заранее определяются стандартные глобальные свойства, которые предоставляются браузером, такие как document и addEventListener .

/*global clearInterval: false, clearTimeout: false, document: false, event: false, frames: false, history: false, Image: false, location: false, name: false, navigator: false, Option: false, parent: false, screen: false, setInterval: false, setTimeout: false, window: false, XMLHttpRequest: false */

В том числе и console, alert, функции которые могут переопределяться глобально, или которые можно расширить, или которые желательно избегать в конечном продукте.

/*global alert: false, confirm: false, console: false, Debug: false, opera: false, prompt: false, WSH: false */

Точка с запятой

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

JSLint ожидает, что каждый оператор должен заканчиваться; (точкой с запятой), исключения в некоторых ситуациях могут быть только для операторов for, function, if, switch, try и while.

Запятая

Оператор запятая, может привести к чрезмерно сложным выражениям и так же может маскироваться некоторые ошибки программирования.

JSLint ожидает увидеть использование запятой в качестве разделителя, но не в качестве оператора (за исключением инициализации и приращения частей оператора).

Область видимости

Во многих языках, блок определяет свою область видимости. Переменные объявленные в этом блоке не видны за его пределами.

В JavaScript, блоки не определяют область видимости. Область видимости определяется только внутри функции. Переменная определенная в функции будет видна всюду в этой функции. Блоки в JavaScript могу в этом плане запутать опытных программистов других языков, из за похожего синтаксиса, что соответственно может привести к ошибкам.

В языках с областью видимости в блоках, как правило, рекомендуется объявлять переменные в том месте, где они непосредственно используются. Но поскольку JavaScript не имеет блочной области видимости, правильно будет объявлять все переменные вверху функции. Рекомендуется использовать один оператор var в фукцнии. Эта рекомендация может быть отключена с помощью опции vars .

Обязательные блоки

JSLint предполагает наличие в конструкциях if, while, do и for операторных скобок, в независимости от того, какое количество операторов внутри этих конструкций присутствует.

JavaScript разрешает следующий способ записи:

if (condition) statement;

Эта форма записи, как известно, способствует появлению ошибок в проектах. По этому JSLint предполагает использование следующей записи:

If (condition) { statements; }

Опыт разработчиков показывает, что такая форма записи является более устойчивой от ошибок.

for in

Цикл for in используется для перечисления всех свойств объекта. Но так же с помощью этого цикла просматриваются абсолютно все свойства, включая те которые были унаследованы через прототип. Получается плохой побочный эффект, когда в качестве свойства мы получаем метод. Если такой цикл написан без осознания этой ситуации, то этот участок кода может вызывать ошибку.

Тело цикла должна быть обернуто в оператор if, который выполняет проверку свойства объекта, для исключения свойств прототипа, например:

For (name in object) { if (object.hasOwnProperty(name)) { .... } }

В большинстве случаев, этого оператора стоит избегать полностью. Лучше всего полагаться на методы, такие как Object.keys и Array.prototype.forEach.

switch

Распространенной ошибкой в операторе switch, является то что забывается размещение break после кострукции case. JSLint ожидает, что каждая конструкция case будет заканчиваться break, return или throw. Каждая конструкция case будет выстраивается на одной линии с оператором switch.

var

JavaScript позволяет определять var в любом месте внутри функции. JSLint в этом случае более строго относится к таким определениям.

JSLint ожидает, что конструкция var будет объявлена только один раз, и до того как будет использована.

JSLint отрицательно смотрит на использование конструкции var внутри операторных скобок, так как они не имеют своей области видимости.

with

Эта конструкция изначально была предназначена для обеспечения сокращенного доступа к свойствам глубоко вложенных объектов. Использование этот конструкции может привести к путанице между использованием переменных и свойств, что может дать непредсказуемое поведение программы. По этому, лучше никогда не использовать этот оператор.

== и!=

И!= операторы выполняют приведение типов перед сравнением. Это плохо, потому что различные конструкции, к примеру такая " trn" == 0 будет true. Это может маскироваться ошибки. JSLint не может достоверно определить, если использование == в настоящее время оправдано, по этому лучше всегда использовать сравнение без неявного приведения типов, а именно === и!==.

С помощью опции eqeq, можно отключить проверку этого оператора.

++ и --

JSLint против использования этих операторов. Включить их спользование можно с помощью опции plusplus .

Битовые операции

В JavaScript нет типа Integer, но есть битовые операторы. Битовые операторы преобразуют операнды с плавающей точкою в целые и обратно, поэтому они не так эффективны как в C или других языках. Они редко бывают полезными в браузерных приложениях. Сходство с логическими операторами может маскировать некоторые ошибки программирования. Опция bitwise разрешает использовать эти операторы.

Eval это зло

Функция eval (и его родственники - setTimeout и setInterval) обеспечивают доступ к компилятору JavaScript. Это иногда необходимо, но в большинстве случаев это указывает на наличие очень плохого стиля программирования. Функция eval является наиболее неправильной особенностью JavaScript.

Конструкторы и new

Конструкторы - это функции, которые предназначены для использования с оператором new. Эта приставка создает новый объект на основе прототипа функции, и связывает этот объект функции с присваиваемой переменной. Если принебречь использованием оператора new для функции конструктора, то возвращаемый результат будет не совсем таким, который ожидался.

JSLint обеспечивает соглашение, что функции конструкторы должны иметь названия первая буква которого будет в верхнем регистре, иначе это будет считаться ошибкой при проверке, если эта функция будет вызываться с оператором new.

Использование оператора new с такими объектами как Number, String, Boolean - будет считаться ошибкой при проверке.

При проверке такой конструкции new Object, JSLint будет подразумевать ее ошибочной, вместо который лучше использовать краткую запись - {}.

Опции

JSLint предлагает несколько опций, которые контролируют его работу. В веб-приложении JSLint, варианты выбираются с использованием флажков и двух полей.

Когда JSLint вызывается как функция, он принимает параметр - объект опций, который позволяет определить приемлемое подмножество JavaScript. На веб-странице версия JSLint http://www.JSLint.com делает это автоматически.

Опции можно также задать в сценарии с помощью / * JSLint * / директивы:

/*jslint nomen: true, debug: true, evil: false, vars: true */

Описание Опция Значение
Tolerate assignment expressions ass true if assignment should be allowed outside of statement position.
Игнорирование битовых операторов bitwise true, если битовые операторы не должны проходить проверку
Разрешить функции браузера browser true, учитываются стандартные глобальные переменные браузера
Разрешить Google Closure идиомы closure true, если Google Closure аннотации должны быть разрешены
Разрешать continue continue true, для того что бы использование countinue игнорировалось
Предложение CouchDB couch true, если нужо что бы функции CouchDB считались глобальными
Разрешать debgger debug true, если оператор debug должен быть разрешен
Разрешать console, alert devel true, если не установлена опция browser, и нужно что бы эти операторы были разрешены
Разрешить == и!= eqeq true, если == и!= операторы должны быть разрешены
Разрешить eval evil true, если eval должен быть разрешен
Пробелы и отступы indent Количество пробелов которые используются для отступов (по умолчанию 4)
Максимальное количество ошибок maxerr Максимальное количество предупреждений для отчета проверки (по умолчанию 50)
Максимальная длинна строки maxlen Максимальное количество символов в строке
Использование прописных букв в начале слова в названии конструктора newcap true, если первые буквы в именах функций конструктора являются обязательными
Учитывать Node.js node true, если Node.js должна учитываться в глобальных переменных
Разрешать прочерк _ в индентификаторах nomen true, если не нужно разрешить использование таких переменных
Остановка на первой ошибке passfail true, если сканирование должно останавливаться на первой ошибке
Разрешить ++ и -- plusplus true, если использование ++ или -- должно быть разрешено
Разрешить отсутствие "use strict" в начале функции sloppy true, для того что бы вставка строки "use strict" была не обязательной
Разрешить TODO комментарии todo true, для того что бы не реагировать на TODO комментарии
Разрешить неиспользуемые параметры unparam true, не показывать предупреждений о неиспользуемых параметрах
Разрешить использование множества var в функции vars true, для множественного использования var в функции
Разрешать грязные пробелы white true, для игнорирования грязных пробелов

I too have had a problem with this. And after quite a while searching for the answer and looking at all the responses by everybody, I think I"ve come up with a viable solution to this.

It seems that most of the answers that I"ve come across is using functions to hold the constants. As many of the users of the MANY forums post about, the functions can be easily over written by users on the client side. I was intrigued by Keith Evetts" answer that the constants object can not be accessed by the outside, but only from the functions on the inside.

So I came up with this solution:

Put everything inside an anonymous function so that way, the variables, objects, etc. cannot be changed by the client side. Also hide the "real" functions by having other functions call the "real" functions from the inside. I also thought of using functions to check if a function has been changed by a user on the client side. If the functions have been changed, change them back using variables that are "protected" on the inside and cannot be changed.

/*Tested in: IE 9.0.8; Firefox 14.0.1; Chrome 20.0.1180.60 m; Not Tested in Safari*/ (function(){ /*The two functions _define and _access are from Keith Evetts 2009 License: LGPL (SETCONST and CONST). They"re the same just as he did them, the only things I changed are the variable names and the text of the error messages. */ //object literal to hold the constants var j = {}; /*Global function _define(String h, mixed m). I named it define to mimic the way PHP "defines" constants. The argument "h" is the name of the const and has to be a string, "m" is the value of the const and has to exist. If there is already a property with the same name in the object holder, then we throw an error. If not, we add the property and set the value to it. This is a "hidden" function and the user doesn"t see any of your coding call this function. You call the _makeDef() in your code and that function calls this function. - You can change the error messages to whatever you want them to say. */ self._define = function(h,m) { if (typeof h !== "string") { throw new Error("I don\"t know what to do."); } if (!m) { throw new Error("I don\"t know what to do."); } else if ((h in j)) { throw new Error("We have a problem!"); } else { j[h] = m; return true; } }; /*Global function _makeDef(String t, mixed y). I named it makeDef because we "make the define" with this function. The argument "t" is the name of the const and doesn"t need to be all caps because I set it to upper case within the function, "y" is the value of the value of the const and has to exist. I make different variables to make it harder for a user to figure out whats going on. We then call the _define function with the two new variables. You call this function in your code to set the constant. You can change the error message to whatever you want it to say. */ self._makeDef = function(t, y) { if(!y) { throw new Error("I don\"t know what to do."); return false; } q = t.toUpperCase(); w = y; _define(q, w); }; /*Global function _getDef(String s). I named it getDef because we "get the define" with this function. The argument "s" is the name of the const and doesn"t need to be all capse because I set it to upper case within the function. I make a different variable to make it harder for a user to figure out whats going on. The function returns the _access function call. I pass the new variable and the original string along to the _access function. I do this because if a user is trying to get the value of something, if there is an error the argument doesn"t get displayed with upper case in the error message. You call this function in your code to get the constant. */ self._getDef = function(s) { z = s.toUpperCase(); return _access(z, s); }; /*Global function _access(String g, String f). I named it access because we "access" the constant through this function. The argument "g" is the name of the const and its all upper case, "f" is also the name of the const, but its the original string that was passed to the _getDef() function. If there is an error, the original string, "f", is displayed. This makes it harder for a user to figure out how the constants are being stored. If there is a property with the same name in the object holder, we return the constant value. If not, we check if the "f" variable exists, if not, set it to the value of "g" and throw an error. This is a "hidden" function and the user doesn"t see any of your coding call this function. You call the _getDef() function in your code and that function calls this function. You can change the error messages to whatever you want them to say. */ self._access = function(g, f) { if (typeof g !== "string") { throw new Error("I don\"t know what to do."); } if (g in j) { return j[g]; } else { if(!f) { f = g; } throw new Error("I don\"t know what to do. I have no idea what \""+f+"\" is."); } }; /*The four variables below are private and cannot be accessed from the outside script except for the functions inside this anonymous function. These variables are strings of the four above functions and will be used by the all-dreaded eval() function to set them back to their original if any of them should be changed by a user trying to hack your code. */ var _define_func_string = "function(h,m) {"+" if (typeof h !== "string") { throw new Error("I don\\"t know what to do."); }"+" if (!m) { throw new Error("I don\\"t know what to do."); }"+" else if ((h in j)) { throw new Error("We have a problem!"); }"+" else {"+" j[h] = m;"+" return true;"+" }"+" }"; var _makeDef_func_string = "function(t, y) {"+" if(!y) { throw new Error("I don\\"t know what to do."); return false; }"+" q = t.toUpperCase();"+" w = y;"+" _define(q, w);"+" }"; var _getDef_func_string = "function(s) {"+" z = s.toUpperCase();"+" return _access(z, s);"+" }"; var _access_func_string = "function(g, f) {"+" if (typeof g !== "string") { throw new Error("I don\\"t know what to do."); }"+" if (g in j) { return j[g]; }"+" else { if(!f) { f = g; } throw new Error("I don\\"t know what to do. I have no idea what \\""+f+"\\" is."); }"+" }"; /*Global function _doFunctionCheck(String u). I named it doFunctionCheck because we"re "checking the functions" The argument "u" is the name of any of the four above function names you want to check. This function will check if a specific line of code is inside a given function. If it is, then we do nothing, if not, then we use the eval() function to set the function back to its original coding using the function string variables above. This function will also throw an error depending upon the doError variable being set to true This is a "hidden" function and the user doesn"t see any of your coding call this function. You call the doCodeCheck() function and that function calls this function. - You can change the error messages to whatever you want them to say. */ self._doFunctionCheck = function(u) { var errMsg = "We have a BIG problem! You\"ve changed my code."; var doError = true; d = u; switch(d.toLowerCase()) { case "_getdef": if(_getDef.toString().indexOf("z = s.toUpperCase();") != -1) { /*do nothing*/ } else { eval("_getDef = "+_getDef_func_string); if(doError === true) { throw new Error(errMsg); } } break; case "_makedef": if(_makeDef.toString().indexOf("q = t.toUpperCase();") != -1) { /*do nothing*/ } else { eval("_makeDef = "+_makeDef_func_string); if(doError === true) { throw new Error(errMsg); } } break; case "_define": if(_define.toString().indexOf("else if((h in j)) {") != -1) { /*do nothing*/ } else { eval("_define = "+_define_func_string); if(doError === true) { throw new Error(errMsg); } } break; case "_access": if(_access.toString().indexOf("else { if(!f) { f = g; }") != -1) { /*do nothing*/ } else { eval("_access = "+_access_func_string); if(doError === true) { throw new Error(errMsg); } } break; default: if(doError === true) { throw new Error("I don\"t know what to do."); } } }; /*Global function _doCodeCheck(String v). I named it doCodeCheck because we"re "doing a code check". The argument "v" is the name of one of the first four functions in this script that you want to check. I make a different variable to make it harder for a user to figure out whats going on. You call this function in your code to check if any of the functions has been changed by the user. */ self._doCodeCheck = function(v) { l = v; _doFunctionCheck(l); }; }())

It also seems that security is really a problem and there is not way to "hide" you programming from the client side. A good idea for me is to compress your code so that it is really hard for anyone, including you, the programmer, to read and understand it. There is a site you can go to: http://javascriptcompressor.com/ . (This is not my site, don"t worry I"m not advertising.) This is a site that will let you compress and obfuscate Javascript code for free.

  • Copy all the code in the above script and paste it into the top textarea on the javascriptcompressor.com page.
  • Check the Base62 encode checkbox, check the Shrink Variables checkbox.
  • Press the Compress button.
  • Paste and save it all in a .js file and add it to your page in the head of your page.
  • От автора: Пожалуй, это будет удивительным, но в JavaScript давно не хватало поддержки констант, т.е. зарегистрированных значений, которые не меняются в процессе выполнения всего вашего скрипта. За неимением каких-либо альтернатив, большинство констант объявлялось с помощью переменных.

    Пример объявления константы с помощью переменной:

    var DAYSINWEEK = 7;

    var DAYSINWEEK = 7 ;

    Это и опасно, и непрактично, поскольку позволяет в любой момент изменить значение переменной DAYSINWEEK в вашем скрипте. Разработчики придумали разнообразные способы, как выделить переменные, являющиеся, как бы, константами, от обычных переменных в JavaScript, начиная от именования переменных ТОЛЬКО ЗАГЛАВНЫМИ БУКВАМИ (лучшая традиция) и заканчивая решениями, о которых я расскажу позже. К счастью, в последней версии ECMAScript (спецификация, являющаяся стандартом) была представлена настоящая константа:

    JavaScript. Быстрый старт

    const DAYSINWEEK = 7;

    const DAYSINWEEK = 7 ;

    И вот теперь к DAYSINWEEK можно обращаться, как к переменной, но вам никогда не удастся изменить ее значение:

    console.log(DAYSINWEEK); > 7 DAYSINWEEK = 8; > error

    console . log (DAYSINWEEK ) ;

    DAYSINWEEK = 8 ;

    > error

    После того, как константа была объявлена (константы должны быть инициализированы с помощью ключевого слова const, а за ним должно идти имя константы, которое следует правилам именования переменных), ее имя будет зарезервировано: вы уже не сможете назвать переменную DAYSINWEEK и иметь константу с таким же именем, или наоборот.

    Ключевое слово const имеет хорошую поддержку в современных браузерах: IE11 и Spartan, Firefox 31+, Opera 12+, Safari 5.1.7+, iOS 7 и выше, вместе с Chrome 36+. Однако, есть несколько важных оговорок:

    В Chrome не поддерживается вывод ошибки при попытке перезаписать константу. Значение константы в любом случае не будет изменено, но неопытный разработчик может подумать, что новое значение было применено, поскольку не было выведено никакой ошибки.

    JavaScript. Быстрый старт

    Изучите основы JavaScript на практическом примере по созданию веб-приложения

    Константы не создают новую область видимости в Webkit. Т.е. константы могут быть видимыми за пределами текущей области видимости.

    Firefox 35 и ниже позволяет вам «на лету» изменить значение const. Это исправлено в версии Firefox 36+.

    Также следует отметить, что проблемы с Webkit возникают, только если не используется режим strict (о котором пойдет речь в одной из следующих статей).

    Можно ли сейчас использовать ключевое слово const в реальных проектах?

    Выбор, использовать ли ключевое слово const в вашем коде или нет, будет зависеть от нескольких факторов: важнее всего то, какими версиями браузеров пользуются посетители ваших сайтов, поскольку использование ключевого слова const будет считаться ошибкой в таких браузерах, как IE10. Если вы хотите использовать ключевое слово const в процессе разработки, но не готовы применять его в реальных проектах, то у вас есть несколько вариантов:

    Вариант 1: использовать транспилер («транспилятор»)

    Транспилеры (transpilers), как следует из названия, трансформируют ваш код во время его компиляции в другой язык: в данном случае из версии спецификации ES6 (в которой появилось ключевое слово const) в ES5. Это позволяет вам писать код на более новой версии языка, но в реальном проекте будет использоваться версия, которая совместима с более широким кругом браузеров. Эдди Озмани (Addy Osmani) составил

    Ноутбук