Я пытался узнать, как добавить тестирование к существующему коду - сейчас читаю Эффективная работа с устаревшим кодом. Я пытался применить некоторые принципы в JavaScript, а теперь пытаюсь извлечь интерфейс.
В поисках создания интерфейсов в JavaScript я не могу найти многого - и то, что я нахожу о наследовании, кажется, это несколько разных способов. (Некоторые люди создают свои собственные базовые классы, чтобы предоставить полезные методы, упрощающие наследование, некоторые используют функции, некоторые используют прототипы).
Как правильно? У вас есть простой пример извлечения интерфейса в JavaScript?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Не существует однозначного правильно, потому что так много людей делают так много разных вещей ... Есть много полезных шаблонов.
Crockford предполагает, что вы «идете с зерном» или пишете javascript способом, который соответствует прототипной природе javascript.
Конечно, он продолжает показывать, что исходная модель, предложенная Netscape, на самом деле не работает. Он называет это «псевдоклассическим» и указывает на множество неправильных направлений и ненужных сложностей, связанных с следованием этой модели.
Он написал функцию «объект» как средство (теперь известную как Object.create ()). Это позволяет создавать очень мощные прототипы паттернов.
Не всегда легко разработать чистый интерфейс, когда вам нужно работать с устаревшим javascript, особенно когда вы имеете дело с большими системами, обычно включающими несколько библиотек, каждая из которых реализует уникальный стиль и разные шаблоны наследования. В общем, я бы сказал, что «правильный способ» наследования - это тот, который позволяет вам написать чистый интерфейс, который хорошо ведет себя в контексте вашего унаследованного кода, но также позволяет вам реорганизовать и устранить старые зависимости с течением времени. .
Принимая во внимание различия между основными шаблонами библиотек, я обнаружил, что наиболее успешный путь в моей работе - это полностью сохранять мои интерфейсы независимыми от интерфейсов библиотеки. Я воспользуюсь библиотекой или модулем, если они будут полезны, но не буду к ним привязан. Это позволило мне провести рефакторинг большого количества кода, отказаться от некоторых библиотек и использовать библиотеки в качестве каркаса, который можно оптимизировать позже.
В соответствии с этим я написал интерфейсы, вдохновленные паттерном паразитического наследования Крокфорда. Это действительно преимущество простоты.
С другой стороны, я уверен, что вы могли бы привести доводы в пользу выбора библиотеки, обеспечения ее соблюдения в вашей команде и соответствия как ее шаблонам наследования, так и ее соглашениям об интерфейсе.
Также посетите Base.js. Дина Эдвардса. Вы можете взглянуть на это здесь, сообщение в блоге говорит само за себя.
Вы смотрите на две разные вещи.
Сначала у вас есть интерфейсы. Наиболее распространенный способ реализации этого - утка («если он похож на утку и крякает, как утка, значит, это утка»). Это означает, что если объект реализует набор методов интерфейса, то это и есть этот интерфейс. Вы реализуете это, имея массив имен методов, определяющих интерфейс. Затем, чтобы проверить, реализует ли объект это вмешательство, вы увидите, реализует ли он эти методы. Вот пример кода, который я придумал:
function Implements(obj, inter)
{
var len = inter.length, i = 0;
for (; i < len; ++i)
{
if (!obj[inter[i]])
return false;
}
return true;
}
var IUser = ["LoadUser", "SaveUser"];
var user = {
LoadUser : function()
{
alert("Load");
},
SaveUser : function()
{
alert("Save");
}
};
var notUser = {
LoadUser : function()
{
alert("Load");
}
};
alert(Implements(user, IUser));
alert(Implements(notUser, IUser));
Теперь у вас есть наследство. JS не имеет встроенного наследования; поэтому вам придется реализовать это вручную. Это просто «копирование» свойств одного объекта на другой. Вот еще один пример кода (не идеальный, но он демонстрирует суть):
function InheritObject(base, obj)
{
for (name in base)
{
if (!obj[name])
obj[name] = base[name];
}
}
var Base = {
BaseFunc : function() { alert("BaseFunc from base"); },
InheritFunc : function() { alert("InheritFunc from base"); }
}
var Inherit = {
InheritFunc : function() { alert("InheritFunc from inherit"); },
AnotherFunc : function() { alert("AnotherFunc from inherit"); }
}
InheritObject(Base, Inherit);
Inherit.InheritFunc();
Inherit.BaseFunc();
Inherit.AnotherFunc();
Base.BaseFunc();
Base.InheritFunc();
Вы, наверное, захотите посмотреть http://www.mootools.net. Это моя любимая реализация классов. Вы также определенно захотите ознакомиться с «Шаблонами проектирования Pro Javascript».
http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X
В этой книге подробно рассказывается о том, как имитировать ООП в javascript.
В javascript нет класса, только объекты. Но если вы настаиваете на эмуляции объектно-ориентированной модели на основе классов, вы можете использовать это:
function ChildClass() {
ParentClass.call(this);
// Write the rest of your constructor function after this point.
};
ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype);
jQuery.extend - это функция «поверхностного копирования» из библиотеки jQuery. Вы можете заменить его любой другой функцией копирования / клонирования объекта.
Prototype предлагает свой собственный взгляд на наследование от http://www.prototypejs.org/api/class/create:
var Animal = Class.create({
initialize: function(name, sound) {
this.name = name;
this.sound = sound;
},
speak: function() {
alert(this.name + " says: " + this.sound + "!");
}
});
// subclassing Animal
var Snake = Class.create(Animal, {
initialize: function($super, name) {
$super(name, 'hissssssssss');
}
});
первое предложение нельзя выделить больше