Javascript.RU

Объявление и проверка типов в примерах

Google Closure Compiler, как и любой кошерный компилятор, старается проверить правильность кода и предупредить о возможных ошибках.

Первым делом он, разумеется, проверяет структуру кода и сразу же выдает такие ошибки как пропущенная скобка или лишняя запятая.

Но, кроме этого, он умеет проверять типы переменных, используя как свои собственные знания о встроенных javascript-функциях и преобразованиях типов,
так и информацию о типах из JSDoc, указываемую javascript-разработчиком.

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

Для включения проверки типов используется флаг --check_types. Кроме того, --warning_level не должен быть QUIET, иначе вы не увидите предупреждений.

Самый очевидный способ задать тип - это использовать аннотацию. Полный список аннотаций вы найдете в документации.

В следующем примере параметр id функции f1 присваивается переменной boolVar другого типа:

/** @param {number} id */
function f1(id) {
	/** @type {boolean} */
	var boolVar

	boolVar = id // (!)
}

Компиляция с флагом --check_types выдаст ошибку:

d.js:6: WARNING - assignment
found   : number
required: boolean
        boolVar = id
                ^

Действительно: произошло присвоение значения типа number переменной типа boolean.

Еще пример, на этот раз вызов функции с некорректным параметром:

/** @param {number} id */
function f1(id) {
	f2(id)  // (!)
}

/** @param {string} id */
function f2(id) { }

Такой функции приведет к ошибке:

f.js:3: WARNING - actual parameter 1 of f2 does not match formal parameter
found   : number
required: string
        f2(id)
           ^

Действительно, вызов функции f2 произошел с числовым типом вместо строки.

Кстати, по этому примеру видно, что тип переменной сохраняется после возврата из функции и других аналогичных операций.

Это возможно, благодаря графу взаимодействий и выведению (infer) типов, которое осуществляет компилятор.

Google Closure Compiler знает, как операторы javascript преобразуют типы. Такой код уже не выдаст ошибку:

/** @param {number} id */
function f1(id) {
	/** @type {boolean} */
	var boolVar

	boolVar = !!id
}

Действительно - переменная преобразована к типу boolean двойным оператором НЕ.
А код boolVar = 'test-'+id выдаст ошибку, т.к. конкатенация со строкой дает тип string.

Google Closure Compiler содержит описания большинства встроенных объектов и функций javascript вместе с типами параметров и результатов.

Например, объектный тип Node соответствует узлу DOM.

Пример проверки:

/** @param {Node} node */
function removeNode(node) {
	node.parentNode.removeChild(node)
}
document.onclick = function() {
	removeNode("123")
}

Выдаст

script.js:6: WARNING - actual parameter 1 of removeNode does not match formal parameter
found   : string
required: (Node|null)
        removeNode("123")

Обратите внимание - в этом примере компилятор выдает required: Node|null. Это потому, что указание объектного типа (не элементарного) подразумевает, что в функцию может быть передан null.

В следующем примере тип указан жестко, без возможности обнуления.

Пример: Объект не-null
/** @param {!Node} node */
function removeNode(node) {
	node.parentNode.removeChild(node)
}
document.onclick = function() {
	removeNode("123")
}

Выдаст

script.js:3: WARNING - actual parameter 1 of Node.prototype.removeChild does not match formal parameter
found   : (Node|string)
required: (Node|null)
        node.parentNode.removeChild(node)
                                    ^

Найти описания встроенных типов и объектов javascript вы можете в файле экстернов: externs.zip находится в корне архива compiler.jar, или в соответствующей директории SVN: http://closure-compiler.googlecode.com/svn/trunk/externs/.

В Google Closure Library есть функции проверки типов: goog.isArray, goog.isDef, goog.isNumber и т.п.

Google Closure Compiler знает о них и понимает, что внутри следующего if переменная может быть только функцией:

if (goog.isFunction(f)) {
  f.apply(1,2,3)
}

Выдаст следующую ошибку:

d.js:2: WARNING - Function Function.apply: called with 3 argument(s). Function requires at least 0 argument(s) and no mo
re than 2 argument(s).
  f.apply(1,2,3)
         ^

То есть, компилятор увидел, что f - это функция, то есть объект типа Function. Метод apply для экземпляра такого объекта принимает только 2 аргумента - обнаружена ошибка. Хорошо, что сейчас, а не позже, в момент запуска.

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

Соответствующие различным типам и ограничениям на типы аннотации вы можете найти в Документации Google. В частности, возможно указание нескольких возможных типов, типа undefined и т.п.

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

Проверка типов javascript, предоставляемая Google Closure Compiler - пожалуй, самая продвинутая из существующих на сегодняшний день.

C ней аннотации, документирующие типы и параметры, становятся не просто украшением, а реальным средством проверки, уменьшающим количество ошибок на production.


Автор: Гость (не зарегистрирован), дата: 20 декабря, 2009 - 17:43
#permalink

как именно скоппиплировать с режимом --check_types

у меня есть bat файлик в нем:

closure\closure\bin\calcdeps.py -i main.js -o compiled -c compiler.jar -f "--compilation_level=ADVANCED_OPTIMIZATIONS" > main-compiled.js

подскажите, пожайлуста!


Автор: Gairon (не зарегистрирован), дата: 30 сентября, 2010 - 18:49
#permalink

Интересная система, вот бы её прикрутить к Eclipse как билдер, чтобы оно код проверяло автоматически.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
1 + 5 =
Введите результат. Например, для 1+3, введите 4.
 
Текущий раздел
Поиск по сайту
Реклама
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Последние комментарии
Последние темы на форуме
Forum