TestComplete: Использование необъявленных переменных в JScript
@ Вс, 19 сентября 2010, 21:10Язык JScript позволяет использовать необъявленные переменные в скриптах. Безусловно, это плохо, так как при первой же попытке считать значение этой переменной мы получим ошибку "Microsoft JScript runtime error. VAR_NAME is undefined", где VAR_NAME – имя необъявленной переменной.
Тем не менее, необъявленные переменные можно использовать в цикле FOR. При этом переменная автоматически будет создана и проинициализирована. Есть лишь одна проблема: при выходе из цикла эта переменная не будет уничтожена.
Представим себе такую функцию:
function UndeclaredVariable()
{
for (i = 1; i <= 3; i++)
{
Log.Message (i);
}
Log.Message (i);
}
Функция в цикле выводит значение переменной i (1, 2, 3), а затем снова выводит значение этой же переменной (4). Вроде бы все замечательно.
А теперь представим, что функция UndeclaredVariable() рекурсивно вызывает саму себя. Например, необходимо пройти по всем элементам дерева, независимо от уровня вложенности, и найти некий определенный элемент.

Первый вариант функции будет выглядеть так:
function TreeFindNode(tree, node)
{
var nodes = tree.Nodes.Count;
for(i = 0; i < nodes; i++)
{
Log.Message("Checking item '" + tree.Nodes.Item(i).Text + "'");
if(tree.Nodes.Item(i).Text.OleValue == node)
return tree.Nodes.Item(i);
}
return null;
}
Она ищет элемент дерева только на первом уровне и отработает нормально. Теперь модифицируем функцию, чтобы проверять все вложенные элементы дерева. Выглядеть она будет так:
function TreeFindNode(tree, node)
{
var ret;
var nodes = tree.Nodes.Count;
for(i = 0; i < nodes; i++)
{
Log.Message("Checking item '" + tree.Nodes.Item(i).Text + "'");
if(tree.Nodes.Item(i).Nodes.Count > 0)
{
ret = TreeFindNode(tree.Nodes.Item(i), node);
if(ret != null)
return ret;
}
if(tree.Nodes.Item(i).Text.OleValue == node)
return tree.Nodes.Item(i);
}
return null;
}
И создадим простую функцию, которая будет искать в дереве элемент Node3:
function Test11()
{
var w = Sys.Process("NETTreeView").WinFormsObject("Form1");
var tree = w.WinFormsObject("treeView1");
Log.Message(TreeFindNode(tree, "Node3") != null);
}
Теперь запустим ее и посмотрим, что выведется в логе.
Checking item 'Node1'
Checking item 'Node1.1'
Checking item 'Node1.2'
Checking item 'Node1.3'
Checking item 'Node5'
Как видим, скрипт пропустил элементы Node2, Node3 и Node4. Это случилось из-за того, что JScript использовал одну и ту же переменную i для всех копий функции TreeFindNode() вместо того, чтобы создавать каждый раз новую копию. Нетрудно представить, что возможны две ситуации: первую мы только что рассмотрели, в ней некоторые элементы были пропущены из-за того, что переменная цикла была изменена второй копией этой же функции. Другая ситуация заключается в том, что вторая копия функции уменьшит значение переменной до значения, которое уже было проверено. Вследствие этого функция будет работать бесконечно.
Чтобы исправить это достаточно лишь указать явное объявление переменной i в начале функции.
function TreeFindNode(tree, node)
{
var ret;
var i;
.............
}

И вот только на днях оказалось, что написать-то я ее написал, а выложить забыл