Зарисовки по JavaScript для .NET разработчиков: определение типа, undefined и неявное приведение
Из предыдущих статей Вы уже убедились, что для работы с переменными в JavaScript вовсе необязательно знать тип переменной. Достаточно объявить саму переменную с помощью ключевого слова var, а затем присвоить ей любой объект (включая функцию). Причем повторное присваивание можно выполнить в любом месте кода (естественно в области видимости), присвоив совершенно другой объект. Однако, часто возникает необходимость узнать тип переменной (объекта, на который ссылается переменная).
Если Вы посмотрите синтаксис JavaScript, то сможете увидеть возможность определения типа с помощью typeof. Реализовав небольшой пример можно прийти к выводу, что оно работает:
1: var n = 3;
2: var s = "Hello"
3:
4: //вернет number
5: alert(typeof n);
6:
7: //вернет string
8: alert(typeof s);
Но, если вы попробуете проделать аналогичное действие с Вашим объектом (функцией), то получите странный результат:
1: function Person() {
2: this.firstName = "Sergey";
3: this.lastName = "Baydachnyy";
4: };
5:
6: var obj = new Person();
7:
8: //вернет object
9: alert(typeof obj);
Сказать, что механизм отработал неправильно – нельзя (таки object), но нам от этого как-то не очень хорошо.
Поэтому, чтобы определить точный тип объекта, используется специальное свойство – constructor. Это свойство, в отличие от prototype, доступно через ссылку на наш объект, и содержит ссылку на объект-конструктор. Таким образом, можно использовать код ниже:
1: //возвращает true
2: alert(obj.constructor==Person);
Вместо constructor можно использовать оператор instanceof, который позволит определить, является ли объект экземпляром заданного типа, но это работает лишь тогда, когда у Вас нет сложной иерархии наследования. Так код ниже напечатает два сообщения TRUE, так как наш объект является как объектом типа Person так и объектом типа Object:
1: function Person() {
2: this.firstName = "Sergey";
3: this.lastName = "Baydachnyy";
4: this.Name = (function () { return this.firstName + " " + this.lastName; });
5: };
6:
7: Person.prototype.testF = (function () { return "testF"; });
8:
9: var obj = new Person();
10:
11: if (obj instanceof Object) {
12: alert("TRUE");
13: }
14:
15: if (obj instanceof Person) {
16: alert("TRUE");
17: }
Кроме типа объекта, очень часто необходимо выделить его свойства и методы. Чтобы перечислить все свойства и методы, доступные в объекте, достаточно использовать индексатор:
1: function Person() {
2: this.firstName = "Sergey";
3: this.lastName = "Baydachnyy";
4: this.Name = (function () { return this.firstName + " " + this.lastName; });
5: };
6:
7: Person.prototype.testF = (function () { return "testF"; });
8:
9: var obj = new Person();
10:
11: for (var i in obj) {
12: alert(obj[i]);
13: }
Код выше вернет два поля с данными и ссылки на два метода, один из которых метод нашего объекта, а второй – метод объекта-прототипа. Чтобы этого избежать и получить только объектные методы, используется специальная функция hasOwnProperty:
1: function Person() {
2: this.firstName = "Sergey";
3: this.lastName = "Baydachnyy";
4: this.Name = (function () { return this.firstName + " " + this.lastName; });
5: };
6:
7: Person.prototype.testF = (function () { return "testF"; });
8:
9: var obj = new Person();
10:
11: for (var i in obj) {
12: if (obj.hasOwnProperty(i)&&(typeof obj[i]=="function")) {
13: alert(obj[i]);
14: }
15: }
В коде выше мы не только выдаем только методы нашего объекта, исключив свойства и методы прототипа.
Поговорив о типе объектов, хотелось бы остановиться на вопросах преобразования типов. Дело в том, что JavaScript пытается выполнить неявное приведение типов везде, где это возможно. В том же C# конструкция типа int i=0; if (i) {…} являлась бы ошибочной, так как переменная типа int не может быть преобразована к типу bool. В JavaScript же реализовано множество неявных преобразований. Поэтому, чтобы избежать возможной неоднозначности, тут используют сразу два оператора сравнений, это == и === (аналогично != и !==). Первый оператор позволяет выполнить неявное преобразование, а второй – нет. Поэтому, всем разработчикам на .NET рекомендую использовать === и !==, чтобы не получить ошибки, которые в .NET были бы невозможны.
Напоследок отмечу, что если вы пытаетесь получить доступ к свойству или методу, которые не определены (или были удалены) в объекте, то получаете специальное значение undefined. Поэтому, если Вы хотите узнать, существует ли метод или свойство внутри объекта, используйте сравнение с этим значением:
1: if (obj.val === undefined) {
2: alert("Undefined");
3: }
Добавить комментарий