Статьи

Исправление экземпляров объекта в JavaScript

Объекты JavaScript Вы знаете свой JavaScript? Взгляните на следующий пример кода и выясните, какое значение отображается в последнем операторе оповещения …


// object constructor
function ObjectConstructor(a, b, c) {

	this.A = a;
	this.B = b;
	this.C = c;
	this.Total = a + b + c;

}

var obj = ObjectConstructor(1, 2, 3);

alert(obj.Total);

Руки вверх всех, кто ответил «6».

Извините, вы не правы. Ответ … ничего — или ошибка, указывающая, что ‘obj’ не определено. Так что пошло не так?

Простой ответ заключается в том, что мы забыли оператор ‘new’, поэтому экземпляр объекта никогда не создается. Заявление должно быть:

 
var obj = new ObjectConstructor(1, 2, 3);

Это простая ошибка. Начинающие разработчики вряд ли заметят отсутствующий оператор, потому что код выглядит практически идентично. Даже опытным кодировщикам может быть сложно отлаживать (тем более что многие считают, что JavaScript — это процедурный язык программирования … который может быть, если вы решите написать его таким образом).

Основная проблема заключается в том, что var obj = ObjectConstructor(1, 2, 3); является совершенно допустимым оператором JavaScript, и механизм интерпретатора не выдаст ошибку. В этом контексте значение obj устанавливается равным значению, возвращенному функцией ObjectConstructor; поскольку значение не возвращается, obj остается «неопределенным» (свойство JavaScript верхнего уровня).

Это вряд ли станет серьезной проблемой, если вы разрабатываете, тестируете и отлаживаете свой собственный код. Однако может быть другое дело, если вы предоставляете библиотеку или API тысячам сторонних разработчиков. В какой-то момент кто-то где-то пропустит этот «новый» оператор, и они обвинят ваш код, а не их.

К счастью, JavaScript — гибкий язык. Мы можем исправить наш конструктор так, чтобы объект создавался правильно, даже если опущен оператор ‘new’:

 
// object constructor
function ObjectConstructor(a, b, c) {

	if (!(this instanceof arguments.callee)) {
		return new ObjectConstructor(a, b, c);
	}

	this.A = a;
	this.B = b;
	this.C = c;
	this.Total = a + b + c;

}

Дополнительный оператор ‘if’ в верхней части конструктора проверяет, является ли ‘this’ экземпляром объекта, и возвращает его в случае необходимости. Код var obj = ObjectConstructor(1, 2, 3); теперь установит obj для экземпляра объекта, и оператором alert будет выведено «6».

Вы когда-нибудь сталкивались с этой проблемой в своем коде или при использовании другой библиотеки?