JavaScript не имеет классов, как говорили другие.Наследование разрешается с помощью прототипирования, которое, по сути, делает не что иное, как создание не удаляемых ссылок на свойства вновь создаваемого объекта.В JavaScript также есть альтернативы для простых объектов данных, а именно, литералы объектов.
Вариант «Класс» в JavaScript должен быть определен следующим образом:
// I use function statements over variable declaration
// when a constructor is involved.
function Person(name) {
this.name = name;
}
// All instances of Person create reference methods to it's prototype.
// These references are not deletable (but they can be overwritten).
Person.prototype = {
speak: function(){
alert(this.name + ' says: "Hello world!"');
}
};
var Mary = new Person('Mary');
Mary.speak(); // alerts 'Mary says: "Hello world!"'
Ссылка this
всегда указываетвладельцу function
.Если вы позвоните Person
без оператора new
, владельцем будет глобальная область (окно).Если вы не используете эту ссылку для назначения свойств вашему экземпляру, тогда свойства будут просто объявлены как переменные.Если вы не используете оператор var
, то эти объявления создадут глобальные переменные, которые являются плохими!
Подробнее об этом
Использование ссылки this
вфункция конструктора чрезвычайно важна, если вы хотите добавить свойства к текущему экземпляру.Без использования this
вы создаете только переменную (которая не совпадает со свойством) и, как уже упоминалось, если вы не используете оператор var, вы создаете глобальные переменные.
function Person(){
name = 'Mary'
}
var p = new Person();
alert(p.name); // undefined, did not use 'this' to assign it to the instance.
alert(name); // 'Mary', boo, it created a global variable!
Используйте это!
function Person(){
this.name = 'Mary'
}
var p = new Person();
alert(p.name); // 'Mary', yay!
alert(name); // undefined, yay!
Обратите внимание, что все, что назначено экземпляру через конструктор функции, НЕ МОЖЕТ БЫТЬ Унаследовано, если вы не назначите его прототипу и не перезапишите его снова в конструкторе функции, чтобы сделать его владельцем.*
Когда вы создаете новый экземпляр с помощью функции, удваивающейся в качестве конструктора, на самом деле происходит следующее.
pseudo code:
copy Person.prototype as person
invoke Person function on person
return person
Собственно, это то, что происходит в каждом классическом языке, когда вы создаете экземпляручебный класс.Но главное отличие JavaScript в том, что он не заключен в красивую инструкцию Class.Изначально JavaScript даже не имел конструкторов функций, но был добавлен позже, потому что SUN требовал, чтобы JavaScript был больше похож на Java.
Литералы объектов
Альтернатива для функцииконструкторы для объектов, которые содержат только внутренние данные и не имеют методов, являются литералами объектов.
var Mary = {
firstName: 'Mary',
lastName: 'Littlelamb'
};
Какой предпочтительный способ объявления внутренних объектов, а не:
// do not ever do this!
var Mary = new Object();
Mary.firstName = 'Mary';
Mary.lastName = 'Littlelamb';
С литералами объектов в вашемнабор навыков, вы можете создать фабричный шаблон для внутренних объектов данных, используя шаблон модуля (который обычно для синглетонов).
var createPerson = function(firstName, lastName){
return {
firstName: firstName,
lastName: lastName
}
}
var Mary = createPerson('Mary', 'Littlelamb');
Это обеспечивает некоторую удобную инкапсуляцию, но может быть толькоиспользуется для внутренних объектов данных.
Еще одна вещь, которую вы можете сделать с литералами объектов и JavaScript, - это делегирование, которое должно быть предпочтительным.
var personMethods = {
speak: function(){
alert(this.firstName + ' says: "Hello world!"');
}
};
var Mary = {
firstName: "Mary",
lastName: "Littlelamb"
};
var Peter = {
firstName: "Peter",
lastName: "Crieswolf"
};
personMethods.speak.apply(Mary); // alerts 'Mary says: "Hello world!"'
personMethods.speak.apply(Peter); // alerts 'Peter says: "Hello world!"'
Почему это должно быть предпочтительным?Поскольку ваши объекты остаются мелкими и читаемыми, даже прототипные ссылки занимают память, а при использовании наследования и «подклассов» вы получаете дочерние экземпляры, которые имеют много неиспользуемых ссылок на методы.Делегация всегда лучше.