Рецепт рассказывает, как пользоваться
Сейчас назвать функцию
назад к списку уроков и рецептов
1. что это и зачем
2. как это работает
3. популярная ошибка
4. пример использования
1. Что это и зачем
Функция
trace("класс Mouse : "+Mouse);
trace("класс Key : "+Key);
trace("класс _global.Mouse : "+_global.Mouse);
trace("класс _global.Key : "+_global.Key);
В Output видим:
класс Mouse : [object Object] класс Key : [object Object] класс _global.Mouse : [object Object] класс _global.Key : [object Object]Это говорит нам о том, что такие объекты действительно есть, и ссылки на них действительно есть в объекте _global.
А теперь попробуем посмотреть, а что еще хранится в _global:
for (var i in _global) {
trace(i);
}
И в Output видим... Ничего, вообще-то, не видим. Никаких Mouse и Key. Они просто скрыты от перебора в начало
2. Как это работает
Синтаксис
ASSetPropFlags(объект,массив имен,флаги защиты[,флаги обнуления]);
Подробнее о параметрах:
- Объект — объект любого типа, внутри которого нужно поставить или снять защиту.
- Массив имен — массив имён свойств и/или методов объекта, которые нужно защитить или с которых нужно снять защиту. В качестве этого аргумента можно передать null, и тогда действие распространится на все свойства и методы объекта.
- Флаги защиты — число, три младших бита которого считаются флагами защиты. То есть, передать можно любое число, но действовать будут только три его младших бита.
Таким образом, число 1 (в двоичном виде: 001) установит защиту отДействие флагов защиты: бит 0 — защита от for..in
бит 1 — защита от удаления
бит 2 — защита от изменения
for..in , но снимет защиту от удаления и изменения. А число 7 (в двоичном виде: 111) установит защиту от всех напастей. Число же 878 (в двоичном виде: 1101101110) установит защиту от изменения и от удаления, но снимет защиту отfor..in . - Флаги обнуления (необязательный параметр) — число, три младших бита которого говорят функции, какие ранее установленные флаги разрешается обнулить. Аналогично предыдущему параметру, число может быть передано любое: только три младших бита будут играть роль.
Эти флаги нужны для того, чтобы при последовательных вызовахASSetPropFlags() не скинуть случайно флаги, установленные до этого. Например, вы установили защиту от удаления, передав число 2 (в двоичном виде 010) в качестве флагов защиты. Потом вы захотели поставить еще и защиту от изменения, и вызвалиASSetPropFlags() еще раз, передав число 4 (в двоичном виде 100) в качетве флага защиты. Как функция должна понять, хотите вы к установленным раньше флагам до бавить еще и флаг защиты от изменения, или же хотите оставить только его, скинув флаги удаления иfor..in ? Для того, чтобы снять неоднозначность, и существуют флаги обнуления.
Если вы опустите при вызове параметр "флаги защиты", функция будет считать, что вы передали 0: никакие флаги защиты обнулять нельзя.Действие флагов
обнуления:бит 0 — разрешается ли обнулить флаг for..in
бит 1 — разрешается ли обнулить флаг удаления
бит 2 — разрешается ли обнулить флаг
изменения
// ставим защиту от изменения и от удаления ASSetPropFlags(объект, массив имён, 6);Здесь флаги обнуления вообще опущены, что означает, что ничего обнулять нельзя. Несмотря на то, что младший бит числа 6 — ноль, флаг
// ставим защиту от удаления ASSetPropFlags(объект, массив имён, 2); // убираем защиту от удаления, // но ставим защиту от изменения и отПервая строчка ставит защиту от удаления, поскольку флаг защиты равен 2 (двоичное 010). Во втором вызове флаг защиты равен 5 (двоичное 101), что означает, что вы хотите установить защиту от изменения и защиту отfor..in ASSetPropFlags(объект, массив имён, 5, 2);
Совет. Для того, чтобы не задумываться каждый раз, какое именно число нужно передать, чтобы обеспечить желаемое значение флагов, используйте функцию parseInt(). Допустим, вы хотите установить флаг защиты от изменения, и обнулить флаги удаления и
var protect = parseInt("100", 2);
var clear = parseInt("011", 2);
ASSetPropFlags(объект, массив имён, protect, clear);
Естесственно, вы можете быстро сообразить что за десятичное число требуется передать и сделать запись короче:
ASSetPropFlags(объект, массив имён, 4, 3);Но задумываться о том, какие флаги устанавливаются, вам придется каждый раз при чтении этого кода. А когда флаги записаны нулями и единицами — вы просто читаете, что происходит, хотя и тратите на это два вызова parseInt().
в начало
3. Популярная ошибка
Во многих материалах об
// неправильно!
ASSetPropFlags(_global,null,6,true);
for(var i in _global){
trace(i)
}
При этом в Output мы увидим всё, что содержится в объекте _global. Якобы, это иллюстрирует возможность снятия защиты от Но здесь допущено две ошибки:
- В качестве флага обнуления передано булево значение.
ASSetPropFlags() , ожидая на этом месте число, приводит true к типу Number, и в результате получается 1. Единица и используется в качестве флага обнуления, что означает, что можно обнулить только флагfor..in . - В добавок к снятию флага
for..in , в этом примере еще и ставятся флаги защиты от удаления и от изменения, ведь 6 в двоичном виде — 110. Иллюстрируя снятие флагаfor..in , совершенно незачем устанавливать два других флага. :)
// правильно!
ASSetPropFlags(_global,null,0,1);
for(var i in _global){
trace(i)
}
В качестве флагов защиты передан ноль (двоичное 000), что означает, что мы хотим снять все флаги. В качестве флагов обнуления передана 1 (двоичное 001), что означает, что обнулить разрешается только флаг for...in.
в начало
4. Пример использования
Убедимся, что это действительно работает. Для наглядности создадим переменные, хранящие флажки, причем будем следовать совету, данному выше, и запишем флаги через parseInt().
// переменные, хранящие флажки:
// overwrite flag - флаг изменения
var o = parseInt("100", 2);
// delete flag - флаг удаления
var d = parseInt("010", 2);
// for flag - флаг for..in
var f = parseInt("001", 2);
// создадим объект для экспериментов и несколько свойств в нем
var test_obj = {};
test_obj.readonly = "свойство только для чтения";
test_obj.godmode = "это не получится удалить";
test_obj.stealth = "свойство скрыто от for..in ";
// перебор до защиты
trace("> до защиты - перебор for..in ")
for (var i in test_obj) {
trace(i+" = "+test_obj[i]);
}
// самое главное
ASSetPropFlags(test_obj, ["readonly"], o);
ASSetPropFlags(test_obj, ["godmode"], d);
ASSetPropFlags(test_obj, ["stealth"], f);
// попробуем удалить, изменить, перебрать for..in
// перебор
trace("\n> результат защиты - перебор for..in ")
for (var i in test_obj) {
trace(i+" = "+test_obj[i]);
}
// изменение
test_obj.readonly += "- изменено";
test_obj.godmode += "- изменено";
test_obj.stealth += "- изменено";
trace("\n> результат защиты - изменение")
trace("readonly = "+test_obj.readonly);
trace("godmode = "+test_obj.godmode);
trace("stealth = "+test_obj.stealth);
// удаление
delete test_obj.readonly;
delete test_obj.godmode;
delete test_obj.stealth;
trace("\n> результат защиты - удаление")
trace("readonly = "+test_obj.readonly);
trace("godmode = "+test_obj.godmode);
trace("stealth = "+test_obj.stealth);
Результат наших трудов в окне Output:
> до защиты - переборfor..in stealth = свойство скрыто отfor..in godmode = это не получится удалить readonly = свойство только для чтения > результат защиты - переборfor..in godmode = это не получится удалить readonly = свойство только для чтения > результат защиты - изменение readonly = свойство только для чтения godmode = это не получится удалить- изменено stealth = свойство скрыто отfor..in - изменено > результат защиты - удаление readonly = undefined godmode = это не получится удалить- изменено stealth = undefined
Иллюстрация на тему флагов обнуления:
var o = parseInt("100", 2);
var d = parseInt("010", 2);
var f = parseInt("001", 2);
var test_obj = {test:"свойство"};
// защитим от удаления и изменения все свойства test_obj
ASSetPropFlags(test_obj, null, o|d);
trace("изначально: test_obj.test = "+test_obj.test);
test_obj.test += "- изменено";
trace("\nизменение: test_obj.test = "+test_obj.test);
for (var i in test_obj) {
trace("перебор: test_obj.test = "+test_obj[i]);
}
delete test_obj.test;
trace("удаление: test_obj.test = "+test_obj.test);
В Output видим:
изначально: test_obj.test = свойство изменение: test_obj.test = свойство перебор: test_obj.test = свойство удаление: test_obj.test = свойствоПопытки изменить и удалить свойство test не увенчались успехом, но цикл
Теперь, допустим, мы хотим поставить защиту от перебора, но отменить защиту от удаления и от изменения.
var o = parseInt("100", 2);
var d = parseInt("010", 2);
var f = parseInt("001", 2);
var test_obj = {test:"свойство"};
// защитим от удаления и изменения все свойства test_obj
ASSetPropFlags(test_obj, null, o|d);
trace("изначально: test_obj.test = "+test_obj.test);
test_obj.test += "- изменено";
trace("\n1:изменение: test_obj.test = "+test_obj.test);
for (var i in test_obj) {
trace("1:перебор: test_obj.test = "+test_obj[i]);
}
delete test_obj.test;
trace("1:удаление: test_obj.test = "+test_obj.test);
ASSetPropFlags(test_obj, null, f, o|d);
// проверим
test_obj.test += "- изменено";
trace("\n2:изменение: test_obj.test = "+test_obj.test);
for (var i in test_obj) {
trace("2:перебор: test_obj.test = "+test_obj[i]);
}
delete test_obj.test;
trace("2:удаление: test_obj.test = "+test_obj.test);
В Output видим:
изначально: test_obj.test = свойство 1:изменение: test_obj.test = свойство 1:перебор: test_obj.test = свойство 1:удаление: test_obj.test = свойство 2:изменение: test_obj.test = свойство- изменено 2:удаление: test_obj.test = undefinedВидим, что после второго вызова
в начало
назад к списку уроков и рецептов