return this.replace(/^\s+|\s+$/g, ""); // Регулярное выражение
};
// Возвращает имя функции. Если функция имеет свойство name (нестандартное),
// возвращает его значение. Иначе преобразует функцию в строку и извлекает имя из нее.
// Для неименованных функций возвращает пустую строку.
Function.prototype.getName = function() {
return this.name || this.toString().match(/function\s*([^(]*)\(/)[1];
};
Методы можно также добавлять в Object, prototype
, тем самым делая их доступными для всех объектов. Однако делать это не рекомендуется, потому что в реализациях, появившихся до ECMAScript 5, отсутствует возможность сделать эти дополнительные методы неперечислимыми. При добавлении новых свойств в Object.prototype
они становятся доступны для перечисления в любом цикле for/in
. В разделе 9.8.1 приводится пример использования метода Object.defineProperty()
, определяемого стандартом ECMAScript 5, для безопасного расширения Object, prototype
.
Возможность подобного расширения классов, определяемых средой выполнения (такой как веб-броузер), зависит от реализации самой среды. Во многих веб-броузерах, например, допускается добавлять методы в HTMLElement.prototype
, и такие методы будут наследоваться объектами, представляющими теги HTML в текущем документе. Однако данная возможность не поддерживается в текущей версии Microsoft Internet Explorer, что сильно ограничивает практическую ценность этого приема в клиентских сценариях.
В главе 3 уже говорилось, что в языке JavaScript определяется небольшое количество типов: null, undefined
, логические значения, числа, строки, функции и объекты. Оператор typeof
(раздел 4.13.2) позволяет отличать эти типы. Однако часто бывает желательно интерпретировать каждый класс как отдельный тип данных и иметь возможность отличать объекты разных классов. Отличать встроенные объекты базового языка JavaScript (и объекты среды выполнения в большинстве реализаций клиентского JavaScript) можно по их атрибуту class
(раздел 6.8.2), используя прием, реализованный в функции classof()
из примера 6.4. Но когда класс определяется с помощью приемов, продемонстрированных в этой главе, экземпляры объектов всегда содержат в атрибуте class
значение «Object», поэтому функция classof()
в данной ситуации оказывается бесполезной.
В следующих подразделах описываются три приема определения класса произвольного объекта: оператор instanceof
, свойство constructor
и имя функции-конструктора. Однако ни один из этих приемов не дает полной гарантии, поэтому в разделе 9.5.4 мы обсудим прием грубого определения типа (duck-typing) - философии программирования, в которой центральное место отводится возможностям объекта (т. е. наличию тех или иных методов), а не его принадлежности к какому-либо классу.
9.5.1. Оператор instanceof
Оператор instanceof
был описан в разделе 4.9.4. Слева от оператора должен находиться объект, для которого выполняется проверка принадлежности к классу, а справа - имя функции-конструктора, представляющей класс. Выражение о instanceof с
возвращает true
, если объект о наследует с.prototype
. При этом наследование необязательно может быть непосредственным. Если о
наследует объект, который наследует объект, наследующий с.prototype
, выражение все равно вернет true
.
Как отмечалось выше в этой главе, конструкторы выступают в качестве наружной вывески классов, а фундаментальная идентификация классов проводится прототипами. Несмотря на то что в операторе instanceof
используется функция» конструктор, этот оператор в действительности проверяет прототип, наследуемый объектом, а не конструктор, с помощью которого он был создан.
Если необходимо проверить, входит ли некоторый определенный прототип в цепочку прототипов объекта без использования функции-конструктора, как промежуточного звена, можно воспользоваться методом isPrototypeOf()
. Например, ниже показано, как проверить принадлежность объекта г к классу range, определенному в примере 9.1:
range.methods.isPrototypeOf(г); // range.methods - объект-прототип.
Один из недостатков оператора instanceof
и метода isPrototypeOf()
состоит в том, что они не позволяют узнать класс объекта. Они лишь проверяют принадлежность объекта указанному классу. Еще более серьезные проблемы начинают возникать в клиентских сценариях JavaScript, когда веб-приложение использует несколько окон или фреймов. Каждое окно или фрейм имеет свой собственный контекст выполнения, и в каждом из них имеется свой глобальный объект со своим собственным набором функций-конструкторов. Два массива, созданные в двух разных фреймах, унаследуют идентичные, но разные объекты прототипов, и массив, созданный в одном фрейме, не будет распознаваться оператором instanceof как экземпляр конструктора Array()
в другом фрейме.
Читать дальше
Конец ознакомительного отрывка
Купить книгу