Open FMRobot opened 9 years ago
Материалы про классы в es6 будут несколько позднее. Что касается терминологии — мне кажется, что точность терминологии начинает играть роль, когда ты уже знаешь какие могут быть подходы к ООП в js. А когда ты им вообще не пользуешься — большой роли это не играет.
На практике достаточно редко можно увидеть нормальное ооп в js. Я говорю и о прототипном, и о попытке имитации классов в строго-типизированных языках, и о классах es6 в том числе. Мне часто приходится видеть чужой код. И — все грустно. Так что меня, например, эта статья порадовала.
Думаю благодаря ей люди, которые вообще не используют ООП, смогут начать это делать.
А как лучше упростить создание экземпляров класса http://prntscr.com/7kfceh ? Чтобы не писать для каждого продукта отдельно?
@LeusMaximus, лучше написать новый метод в ProductCollection
, который будет добавлять продукты массивом.
Я сделал пример на CodePen. http://codepen.io/vyushin/pen/oXoBqx
Что это за сеньор, пихающий шаблоны в модель?
@ogonkov, примеры максимально простые, чтобы лучше понять тему. Клиентская шаблонизация - это отдельная большая тема.
Конечно в боевых условиях модель и шаблоны надо разделять.
@SilentImp, я тоже редко встречаю подобный подход в повседневной разработке! У меня пока нет точного ответа почему так происходит, но это правда грустно. По большей части это встречается во фреймворках и API. Например Backbone, Ext JS, Ymaps API и т. п.
Такой подход медленнее на старте, но зато потом легче поддерживать приложение.
JavaScript устроен таким образом, что все в нем является объектами.
Например null
или undefined
?
Мало того: значения типов string
, number
и boolean
то же не являются объектами, а только ведут себя так иногда (такая встроенная магия).
var bar = "Вася";
bar.foo = "Пертрович" ;
// Скрытая магия:
// bar = new String(bar);
// bar.foo = "Пертрович" ;
// bar = bar.toString();
// А следоватешльно
console.log(bar);
// Вася
console.log(bar.foo);
// undefined
Использовать String
, Number
и Boolean
вообще стоит ограничено, если вообще стоит.
То есть если ты решил заняться разработкой на JS, то до всяких имитаций ООП, используя прототипное наследование, нужно ознакомится с http://bonsaiden.github.io/JavaScript-Garden/ru/
@fpinger,
Например null или undefined?
Постараюсь выразить свою мысль в коде:
console.log(typeof null) // object
console.log(typeof new Boolean(true)) // object
console.log(typeof new Number(1)) // object
console.log(typeof new String('1')) // object
console.log(typeof new Array([1, 2])) // object
@vyushin typeof'у ж нельзя верить. null это не объект. Результат typeof null == "object" — это официально признанная ошибка в языке, которая сохраняется для совместимости. На самом деле null — это не объект, а отдельный тип данных. И в целом, согласен с @fpinger — использовать Number String и Boolean в принципе антипаттерн, неспроста мдн и прочие js garden’ы настоятельно рекомендуют использовать эти примитивы в обход конструкторов
@a-wart, JS слаботипизированный язык:
1 == new Number(1) // true
1 === new Number(1) // false
Вы говорите о типах, а я говорю про объекты. Не путайте, прошу вас. Это разные понятия.
@vyushin вы утверждаете, что «всё в js является объектами». мы говорим: нет, не всё. например, null вы говорите: console.log(typeof null) // object мы говорим: это признанная ошибка языка и на самом деле null это не объект. вы говорите, что мы что-то путаем. я не вижу путаницы в своих рассуждениях, к сожалению, только в ваших.
и раз уж вы применяете в своём примере typeof то тоже говорите о типах.
@a-wart, Вы правы, успокойтесь. В JS не всё является объектами, например (), {}, [] в JS не являются объектами. Запятые, символы +, -, =, : в JS не являются объектами. Я пропустил какой-то символ? :)
@vyushin я спокоен, не переживайте. Боюсь, вы пропустили целостное понимание того, о чём пытаетесь писать. В остальном претензий не имею.
Уточнения ради, все-таки {} и [] в JS являются обьектами
@DeLaGuardo, а так }{, ][ ? ))
@vyshin, Вы что-то пытаетесь этим доказать? Не понимаю, правда, что :)
В JavaScript более распространено такое понятие как функции-конструкторы, но для удобства я буду называть их классами.
Итак, ООП... базовыми понятиями ООП являются наследование и инкапсуляция. Сделайте пожалуйста функцию-конструктор, которая будет наследована от другой функции-конструктора частично переопределяя ее функционал. Потом "для удобства" называйте ее классом, пока вы этого не сделаете - пожалуйста, даже не так - умоляю!! не смешивайте эти два понятия.
@vyshin, если вас задела фраза:
То есть если ты решил заняться разработкой на JS
То прошу извинения, но она к абстрактному начинающему разработчику на JS, а не лично к вам. Я, думаю, она повлияла на градус эмоций.
Если null объект, то покажите мне его родословную, как объекта :)
@DeLaGuardo, это базовые вещи. :) Функции-конструкторы поддерживают наследование через прототип.
@vyushin, частичное, я говорил про частичное наследование
@DeLaGuardo, опять же через прототип. :) Можно расширить один прототип другим прототипом, можно каким-то конкретным методом. Пожалуйста, в JS это есть. Пользуйтесь на здоровье. :)
@fpinger, Если вам не по душе моя терминология, то я не стану вас переубеждать. :) Кто смог понять идею статьи целиком, не придираясь к отдельным конкретным словам, тому респект и уважуха, кто её не понял - очень жаль.
@vyshin, я не против понятного кода, но при этом я за правильное понимание JS. :)
@vyushin В JS есть простые типы, такие как число или строка, но есть и объекты — число и строка. Если попытаться скажем использовать метод объекта строка для переменной простого типа строка, то из неё будет создан объект типа строка и метод будет вызван.
Про типы, кстати, достаточно подробно написано в спецефикации ECMA. И правила их преобразования тоже.
Так что да, «все в JS — объект» это преувеличение с формальной точки зрения.
@SilentImp, конечно преувеличение. Ведь символы }, {, [, ], +, -, = и т. д. не являются объектами. :)
@vyushin, литералы могут объявлять как объекты, так и не объекты. Но ведь речь не об этом.
@fpinger, вы изучаете английский? Так вот, в английском языке одни и те же слова имеют разный смысл в зависимости от контекста. Тут то же самое. Перестаньте придираться к словам и смотрите на контекст. Что за детский сад?
@vyushin, кстати относительно объектного подхода. А вы пробовали функциональный? В JS он позволяет писать ещё более понятный код, чем объектно ориентированный. :)
@fpinger 👍 за фп! мне нравится ramda, а вам?
@iamstarkov, спасибо за информацию. Добавил в тудушку посмотреть. Честно. я в теме фп недавно.
Сделайте пожалуйста функцию-конструктор, которая будет наследована от другой функции-конструктора частично переопределяя ее функционал. Потом "для удобства" называйте ее классом, пока вы этого не сделаете - пожалуйста, даже не так - умоляю!! не смешивайте эти два понятия.
function Parent() {}
Parent.prototype.someMethodA = function(){};
Parent.prototype.someMethodB = function(){};
function Child() {}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.someMethodA = function(){};
Теперь можно называть классом, да? :)
Статья мне понравилась. Было интересно посмотреть, как одна и та же задача выполняется с помощью разных подходов (в зависимости от уровня разработчика). Себя смело причисляю к разряду Junior'ов.
Поводу высказывания "JavaScript устроен таким образом, что все в нем является объектами." и дальнейшего обсуждения хочу сказать, что уже не в первом источнике говорится об обратном. Например, в "Eloquent JavaScript" (http://eloquentjavascript.net/04_data.html#h_mT4YQfwHp6):
"Values of type string, number, and Boolean are not objects, and though the language doesn’t complain if you try to set new properties on them, it doesn’t actually store those properties. The values are immutable and cannot be changed."
Насколько я вообще понимаю, для скалярных значений в JS создается временная обертка, которая и позволяет получить доступ к встроенным свойствам или методам.
@ditransler, спасибо. :) Если кому-то нравится копать глубоко, то это личное дело каждого. Некоторым вообще нравится на ассемблере писать. Да ради Бога! Пусть хоть на голове стоят.
Есть натуральное число 9
. Ну да - это число. Есть строка "I'm a string!"
. Да - это строка. Есть булев тип и т. д. Да, да, да. Это всё так. Это типы и они есть. Никто не говорил, что типов не существует и что типы - это объекты. Не надо придираться к слову "всё", я вас очень прошу.
0; // это число
"I'm a string"; // Это строка
true; // Булев тип
Речь не о том. Со всеми этими типами так или иначе мы взаимодействуем, как с объектами. Не всегда (а то опять скажете, что слишком обобщаю), понятное дело. Это само собой разумеется! Если мы работаем с ними, как с объектами, то имеем полное право назвать их объектами. И я буду называть их ОБЪЕКТАМИ. По тому что я работаю с ними, как с ОБЪЕКТАМИ и рассказываю о них, как об ОБЪЕКТАХ.
var str = "I'm a string"; // Это строка. Тип "string". Но у нее есть методы. Значит это объект.
str.toUpperCase(); // Вызываем метод ОБЪЕКТА String
Другой пример:
var num = 671; // Это натуральное число. Тип "number". Но у него есть методы. Значит это объект.
num.toString(); // Вызываем метод ОБЪЕКТА Number
Есть и третий пример:
var str = "I'm a string";
str.substr(1, 2); // Передаваемые аргументы 1 и 2 не являются объектами. Это целые числа.
Какой вывод мы можем сделать? В JavaScript представление типов может быть как в натуральном виде, так и в виде объектов. Вот и разобрались.
Здравствуйте. У меня глупый вопрос :) Senior developer создал очень интересную конструкцию. А потом вызвал её для трех продуктов. Создал три экземпляра объекта.
А что делать, если у нас 50 товаров? Создавать для каждого экземпляр:
... = new Product({ ... });
?
А если 500? А если 10000 ?
Ой, что у нас с потреблением памяти-то будет твориться...
Да, я теперь понимаю, почему современные веб-страницы так дико тормозят на моем стареньком ноуте! Упоение технологиями без оглядки на реальность.
@KarelWintersky, хороший вопрос и правильный. Выше в комментах я говорил о методе addProducts для добавления товаров одним массивом. Это хардкодный вариант просто для наглядности. В реальности лучше подгружать этот массив аяксом с сервера в json или XML формате.
В случае, когда у нас много товаров мы можем сделать пагинацию, аякс скроллинг и т. п., подгружая данные динамически.
По поводу "Объектов" и "Необъектов". Я думаю что лучше вещи называть своими именами, чтобы не сбивать с толку людей, которые только начали изучать JS. Строка это строка, она не есть объект, но если мы на ней вызываем метод объекта String
, то парсер автоматически, на лету, создает объект обвертку, чтобы выполнить метод, но с самой строкой ничего не происходит, она остается неизменной. То что, со строкой можно обращаться как с объектом, это еще не значит, то ее можно называть объектом.
срочно необходимо понизить градус дискуссии
@vyushin,
В реальности лучше подгружать этот массив аяксом с сервера в json или XML формате.
Честно говоря, мне этот подход не кажется хорошим. У нас конечно эпоха быстрых интернетов и сверхбыстрых браузеров, но ситуацию, когда клиенту приезжает страничка на килобайт, которая загружает JS-ок на мегабайт, которые потом с сервера еще дергают в несколько десятков запросов еще кучу данных, потом JS это все рендерит на клиенте и показывает в удобоваримой форме... такую ситуацию нормой я не считаю ;)
Потому и назвал ситуацию "упоением от технологий". Я внимательно изучил текст, вынес кое что интересное для себя и решил остановиться на втором варианте. Осознанно :)
В реальности лучше подгружать этот массив аяксом с сервера в json или XML формате.
Отлично :) Но ведь мы потом все равно проходим по этому массиву и импортируем данные в память, пусть и в цикле. Да, код страницы меньше. Но я говорю про потребление оперативки и cpu-time.
Как жить с таким?
Вопросы пагинации оставим в стороне: "Клиент должен видеть все доступные ему товары, никакой пагинации" - я такое слышал не раз.
Аякс-скроллинг - не панацея. Да, изначально на странице товаров мало и мало объектов. А когда мы пролистаем вниз? Мы же не можем убрать объекты из памяти только потому, что они оказались за пределами browser.viewport
?!
Похожая ситуация получается, когда мы просматриваем архив (ре)постов тумблер-блога. Но там то, хоть и используется аякс-скроллинг - просто добавляются элементы в DOM. Просто элементы, просто в DOM (хоть и превьюшки картинок/постов). Тем не менее, на каком-то этапе инстанс хрома улетает далеко за 800 мегов.
Нормально ли это? Не думаю. Что с этим делать? Не знаю.
Как жить с таким?
Мы* решаем проблемы бизнеса, а не дрочим на байты.
*ответственные разработчики.
байты, а особенно много-много байтов это проблемы клиентов, а соответственно и проблемы бизнеса
@alexeyraspopov, сняли с языка выражение "байтодротство". :)
@KarelWintersky, желаю вам удачи в экономии байтов и ЦПУ. Родина вас не забудет.
@iamstarkov :+1: Осталось провести тесты и посрамить оппонентов.
@vyushin, кто с ассемблера начинал, всегда помнит о байтах и ЦПУ.
@KarelWintersky, ахах. Во всем есть крайности. Думаю люди, которые не впадают в крайности способны сосредоточиться на более важных вещах и решить поставленные задачи более качественно в кратчайшие сроки.
@vyushin, вы отстаиваете позицию "подход сениора более качественный и занимает меньше времени разработки"? :)
Все зависит от того для чего и кого создается приложение. Если это бизнес, то там все очень просто, нет клиентов, нет бизнеса. Например, не зря же написаны JS библиотеки для поддержки старых, и горячо любимых всеми разработчиками, браузеров ІE.
@KarelWintersky, не совсем. Я считаю, что подход сениора более медленный на старте, но в долгосрочной перспективе полностью оправдывает себя. Тем более для команды разработчиков.
Мы оперируем данными с веб-страницы и используем строковую математику.
Мне кажется, подход миддла некорректен. Подозреваю, автор совершил эту ошибку намеренно - внёс селектор внутрь init()
init: function(selector) {
$(selector).each(function() { ... });
}
и
productDiscount.init('.products li' );
не зря же написаны JS библиотеки для поддержки старых, и горячо любимых всеми разработчиками, браузеров ІE.
Совсем недавно друг допиливал внутренний портал для одного крупного российского банка. С большим трудом ему удалось убедить заказчика, что IE6 поддерживать не надо. В ответ его обязали поддерживать IE7. Почему? Потому что IE7 внутри локальной сети банка - _стандарт_. Мнение разработчика никого не интересует.
@iamstarkov: сильно мешает
.comments form textarea { resize: none; }
Очередная статья, где автор открыл для себя функции-конструкторы и разобрался в прототипном наследовании, это конечно, хорошо, но есть но: → запутал всех, обозвав функции-конструкторы сначала классами, а потом моделью. → зачем-то на пути к идеальному решению несколько раз изменил исходные условия, добавил клиентскую шаблонизацию и рассказал про как хорошо размещать класс в каталоге модель.
прочитав заголовок, я ждал описания ES6 классов, ну или хотя бы небольшой статьи про сахар class в CoffeeScript. В общем, рассказать про конструкторы, создание объектов и прототипы это хорошо, называть это популистским термином «программирование классами в веб-приложениях» — плохо. Плохо, потому что в js на текущий момент НЕТ классов, но есть прототипы. Плохо путать людей и называть синее мягким.