// как toString, обрабатываются некорректно, если явно не проверять их.
var extend = (function() { // Присвоить значение, возвращаемое этой функцией
// Сначала проверить наличие ошибки, прежде чем исправлять ее.
for(var р in {toString:null}) {
// Если мы оказались здесь, значит, цикл for/in работает корректно
// и можно вернуть простую версию функции extend()
return function extend(o) {
for(var і = 1; і < arguments.length; i++) {
var source = arguments[i];
for(var prop in source) o[prop] = source[prop];
}
return o;
};
}
// Если мы оказались здесь, следовательно, цикл for/in не перечислил
// свойство toString тестового объекта. Поэтому необходимо вернуть версию extend(),
// которая явно проверяет неперечислимость свойств прототипа Object.prototype.
// Список свойств, которые необходимо проверить
var protoprops = ["toString", "valueOf", "constructor", "hasOwnProperty",
"isPrototypeOf". "propertylsEnumerable". "toLocaleString"];
return function patched_extend(o) {
for(var і = 1; і < arguments.length; i++) {
var source = arguments[i];
// Скопировать все перечислимые свойства
for(var prop in source) o[prop] = source[prop];
// А теперь проверить специальные случаи свойств
for(var j = 0; j < protoprops.length; j++) {
prop = protoprops[j];
if (source.hasOwnProperty(prop)) o[prop] = source[prop];
}
}
return o;
};
}0);
Как и в большинстве языков программирования, в JavaScript используются лексические области видимости. Это означает, что при выполнении функций действуют области видимости переменных, которые имелись на момент их определения, а не на момент вызова. Для реализации лексической области видимости внутренняя информация о состоянии объекта функции в языке JavaScript должна включать не только программный код функции, но еще и ссылку на текущую цепочку областей видимости. (Прежде чем продолжить чтение этого раздела, вам, возможно, следует повторно прочитать сведения об областях видимости переменных и цепочках областей видимости в разделах 3.10 и 3.10.3.) Такая комбинация объекта функции и области видимости (множества связанных переменных), в которой находятся переменные, используемые вызываемой функцией, в литературе по информационным технологиям называется замыканием}
Технически все функции в языке JavaScript образуют замыкания: они являются объектами и имеют ассоциированные с ними цепочки областей видимости. Большинство функций вызываются внутри той же цепочки областей видимости, которая действовала на момент определения функции, и в этой ситуации факт образования замыкания не имеет никакого значения. Интересные особенности замыканий начинают проявляться, когда их вызов производится в другой цепочке областей видимости, отличной от той, что действовала на момент определения. Чаще всего это происходит, когда объект вложенной функции возвращается функцией, вмещающей ее определение. Существует множество мощных приемов программирования, вовлекающих такого рода вложенные функции-замыкания, и их использование довольно широко распространено в программировании на языке JavaScript. Замыкания могут выглядеть малопонятными при первом знакомстве, однако вам необходимо хорошо понимать их, чтобы чувствовать себя уверенно при их использовании. 14 14 Это старый термин, который отражает тот факт, что переменные функции привязаны к цепочке областей видимости, вследствие чего функция образует «замыкание» по своим переменным.
Первый шаг к пониманию замыканий - знакомство с правилами лексической области видимости, действующими для вложенных функций. Взгляните на следующий пример (который напоминает пример в разделе 3.10):
var scope = "global scope”; // Глобальная переменная
function checkscope() {
var scope = "local scope"; // Локальная переменная
function f() { return scope; } // Вернет значение локальной переменной scope
return f();
}
checkscope() // => "local scope"
Реализация замыканий
Понять суть замыканий будет совсем несложно, если усвоить правило лексической области видимости: во время выполнения функции используется цепочка областей видимости, которая действовала в момент ее определения. Однако некоторые программисты испытывают сложности при освоении замыканий, потому что не до конца понимают особенности реализации. Известно, думают они, что локальные переменные, объявленные во внешней функции, прекращают свое существование после выхода из внешней функции, но тогда как вложенная функция может использовать цепочку областей видимости, которая больше не существует? Если вы задавали себе такой вопрос, значит, у вас наверняка есть опыт работы с низкоуровневыми языками программирования, такими как С, и аппаратными архитектурами, использующими стек: если локальные переменные размещать на стеке, они действительно прекращают свое существование после завершения функции.
Читать дальше
Конец ознакомительного отрывка
Купить книгу