- Команда gulp —tasks выводит дерево команд, а начиная с 4.0 - и синхронно-асинхронные цепочки series/parallels.
- Одной цепочке тасков может быть присвоено несколько значений, в зависимости от условий (if-else) и переданных в series/parallels тасков.
- Можно вызывать .src() прямо в цепочке между .src() и .dest(). Пример:
exports.default = function() {
return src('src/*.js')
.pipe(babel())
.pipe(src('vendor/*.js'))
.pipe(uglify())
.pipe(dest('output/'));
}
То же можно проделать и с .dest() - для сохранения состояния файла и обновления пути к нему.
- Есть два значимых режима .src(): Stream и Buffer. Buffer - стандартный режим: в нём метод считывает файлы в память, где и обрабатывает. Stream не читает файлы, что удобно для очень больших из них, вроде фильмов. В этом режиме файл разбивается на небольшие чанки и "течет" от входа к выходу, о чём красноречиво говорит его название. :) Переключить режимы можно опцией buffer.
- Negative globs - это строка, которую принимает src, в контексте отрицания:
gulp.src(['app/**/*.js', '!app/node_modules']).
Отрицательный glob должен следовать в массиве после положительного. В нём не должно быть неопределенных символов - так он наиболее производителен.
Чтобы не писать каждый раз глобальный объект gulp, а ограничиться src, dest и проч., нужно присвоить им всем require:
const { src, dest, series } = require('gulp');
- В сущности, globs - диалект регулярных выражений. Почитать про них можно тут: https://github.com/begin/globbing#what-is-globbing
- Одной цепочке тасков может быть присвоено несколько значений, в зависимости от условий (if-else) и переданных в series/parallels тасков.
- Можно вызывать .src() прямо в цепочке между .src() и .dest(). Пример:
exports.default = function() {
return src('src/*.js')
.pipe(babel())
.pipe(src('vendor/*.js'))
.pipe(uglify())
.pipe(dest('output/'));
}
То же можно проделать и с .dest() - для сохранения состояния файла и обновления пути к нему.
- Есть два значимых режима .src(): Stream и Buffer. Buffer - стандартный режим: в нём метод считывает файлы в память, где и обрабатывает. Stream не читает файлы, что удобно для очень больших из них, вроде фильмов. В этом режиме файл разбивается на небольшие чанки и "течет" от входа к выходу, о чём красноречиво говорит его название. :) Переключить режимы можно опцией buffer.
- Negative globs - это строка, которую принимает src, в контексте отрицания:
gulp.src(['app/**/*.js', '!app/node_modules']).
Отрицательный glob должен следовать в массиве после положительного. В нём не должно быть неопределенных символов - так он наиболее производителен.
Чтобы не писать каждый раз глобальный объект gulp, а ограничиться src, dest и проч., нужно присвоить им всем require:
const { src, dest, series } = require('gulp');
- В сущности, globs - диалект регулярных выражений. Почитать про них можно тут: https://github.com/begin/globbing#what-is-globbing
GitHub
GitHub - begin/globbing: Introduction to "globbing" or glob matching, a programming concept that allows "filepath expansion" and…
Introduction to "globbing" or glob matching, a programming concept that allows "filepath expansion" and matching using wildcards. - GitHub - begin/globbing: Int...
В JavaScript всё является объектом. Поэтому конструктор new Object ведет себя необычно: в зависимости от параметра он создает не пустой объект, а объект того типа данных, который ему был передан, с характерными методами. Такой конструктор внутри создает перевызов - new Object становится new Number.
const num = new Object(1);
num.constructor === Number // true
!!! На практике использование конструктора для создания объекта - антипаттерн. Ведь, когда вместо явно обозначенного аргумента ему передается переменная, код становится непредсказуемым и нечитаемым. Никогда нельзя забывать о читаемости кода коллегами.
const num = new Object(1);
num.constructor === Number // true
!!! На практике использование конструктора для создания объекта - антипаттерн. Ведь, когда вместо явно обозначенного аргумента ему передается переменная, код становится непредсказуемым и нечитаемым. Никогда нельзя забывать о читаемости кода коллегами.
!!! На практике конструкторы используются для штамповки однотипных объектов, чтобы не создавать каждый руками.
Их методы нужно выносить за пределы конструктора:
1. так удобнее расширять их. (заметка: узнать про обстановку дел в ЕS6/7);
2. метод, указанный прямо в конструкторе, первый из унаследованных от него объектов не получит.
Конструкторы нужно обязательно вызывать с ключевым словом new. Иначе контекст - this - присвоится в нём глобальному объекту.
Предотвратить ошибку можно так:
function new User(name) {
// code....
if(!(this.instanceof User)) {
return new User(name);
}
this. name = name;
}
}
Ключевое слово instanceof проверяет, каким конструктором создан объект. Слева указывается объект, справа - конструктор. Если значения не совпадают, выбрасывается false и на основе этого можно строить определенную логику.
!!! На практике это нужно, чтобы код работал безотказно у других разработчиков. Именно так работают встроенные конструкторы JS.
Их методы нужно выносить за пределы конструктора:
1. так удобнее расширять их. (заметка: узнать про обстановку дел в ЕS6/7);
2. метод, указанный прямо в конструкторе, первый из унаследованных от него объектов не получит.
Конструкторы нужно обязательно вызывать с ключевым словом new. Иначе контекст - this - присвоится в нём глобальному объекту.
Предотвратить ошибку можно так:
function new User(name) {
// code....
if(!(this.instanceof User)) {
return new User(name);
}
this. name = name;
}
}
Ключевое слово instanceof проверяет, каким конструктором создан объект. Слева указывается объект, справа - конструктор. Если значения не совпадают, выбрасывается false и на основе этого можно строить определенную логику.
!!! На практике это нужно, чтобы код работал безотказно у других разработчиков. Именно так работают встроенные конструкторы JS.
В JS массивы - это объекты, или ассоциативные массивы в других языках. В C# массив - непрерывная цепочка байтов в оперативной памяти. Нельзя просто добавить массиву элемент, не создав новый массив.
Конструктор new Array работает специфично:
Любое значение, переданное ему как единственный аргумент, становится указанием, сколько неопределенных - undefined - элементов массива создать. Попавшая в конструктор строка или число типа float вызовет ошибку, целое число - создаст undefined-значения по количеству этого числа.
!!! На практике не нужно использовать конструктор new Array. Литеральная запись функционально повторяет его и превосходит в безопасности. Справедливости ради, я и не использую конструкторы.
!!! То же самое о конструкторе new Number. Если код завязан на проверку типов - то созданное через конструктор число вызовет ошибку.
Конструктор new Array работает специфично:
Любое значение, переданное ему как единственный аргумент, становится указанием, сколько неопределенных - undefined - элементов массива создать. Попавшая в конструктор строка или число типа float вызовет ошибку, целое число - создаст undefined-значения по количеству этого числа.
!!! На практике не нужно использовать конструктор new Array. Литеральная запись функционально повторяет его и превосходит в безопасности. Справедливости ради, я и не использую конструкторы.
!!! То же самое о конструкторе new Number. Если код завязан на проверку типов - то созданное через конструктор число вызовет ошибку.
При вызове метода простой переменной -
string.length()
- интерпретатор временно создаст объект string, методом которой код и воспользуется.
Значениям нельзя присваивать свойства, как объектам. А вот если создать примитив через конструктор - то запросто.
!!! На практике не нужно модифицировать глобальные объекты. Эта проблема специально была решена с помощью примитива symbol в ES6. Из этого следует, что моя библиотека, модифицирующая глобальный объект Date ради пустякового значения, - пример антипаттерна.
string.length()
- интерпретатор временно создаст объект string, методом которой код и воспользуется.
Значениям нельзя присваивать свойства, как объектам. А вот если создать примитив через конструктор - то запросто.
!!! На практике не нужно модифицировать глобальные объекты. Эта проблема специально была решена с помощью примитива symbol в ES6. Из этого следует, что моя библиотека, модифицирующая глобальный объект Date ради пустякового значения, - пример антипаттерна.
Окончательная расстановка точек над функциями, ч.1:
—- Function Declaration - это Объявление Функции. То есть, такая запись:
function foo() {}
—- Function Expresson - это функциональное выражение. То есть, фунция, присвоенная переменной:
const foo = function() {}
—- Named Function Expression - это такое функциональное выражение, где переменной присвоена уже именованная функция:
const foo = function bar() {}.
—- Function Declaration - это Объявление Функции. То есть, такая запись:
function foo() {}
—- Function Expresson - это функциональное выражение. То есть, фунция, присвоенная переменной:
const foo = function() {}
—- Named Function Expression - это такое функциональное выражение, где переменной присвоена уже именованная функция:
const foo = function bar() {}.
!!! Практические применения немедленно вызываемых функций - не только изолирование кода от глобальной области видимости. Иногда полезно передать такой фунции глобальный объект под псевдонимом:
(function(global){
global.prototype... // код фнукции
)(this));
Здесь под псевдонимом global в функцию попадает объект window. Это слово - табу для компилятора: оно не ужимается при минимизации и оптимизации. Global же свободно принимает вид "g". Поэтому такой прием хорошо влияет на производительность.
(function(global){
global.prototype... // код фнукции
)(this));
Здесь под псевдонимом global в функцию попадает объект window. Это слово - табу для компилятора: оно не ужимается при минимизации и оптимизации. Global же свободно принимает вид "g". Поэтому такой прием хорошо влияет на производительность.
В нативном JS у classList есть метод .toggle() - аналог метода из jQuery. Просто и приятно!
Второй приятный метод classList - .contains(). Проверяет присутствие переданного класса. Удобно вместо value для множественных классов или отхода к ID.Ъ
В функции можно передавать объекты. Даже без реализации паттерна модуль. Объекты - отличный способ доставки, например, атрибутов. Доставленный объект перебирается в функции, и содержимое присваивается, куда надо.
Второй приятный метод classList - .contains(). Проверяет присутствие переданного класса. Удобно вместо value для множественных классов или отхода к ID.Ъ
В функции можно передавать объекты. Даже без реализации паттерна модуль. Объекты - отличный способ доставки, например, атрибутов. Доставленный объект перебирается в функции, и содержимое присваивается, куда надо.
Wordpress
- Тег шаблона - это запись вида <?php the_ID() ?>. Такая запиись вставляется в HTML-код шаблона и модифицирует его по информации из базы, которую вытянет функция.
- Шаблон - это PHP-файл, где закодированы общие элементы страницы, а контент выводится динамически с помошью тегов и циклов.
- Некоторые теги принципиально не работают вне цикла - или, работая, используют только последний пост.
- Под постом в WP можно понимать любой повторяющийся блок контента. Например, карточка товара - в некотором роде пост. (сомнительно, проверить)
- Тег шаблона - это запись вида <?php the_ID() ?>. Такая запиись вставляется в HTML-код шаблона и модифицирует его по информации из базы, которую вытянет функция.
- Шаблон - это PHP-файл, где закодированы общие элементы страницы, а контент выводится динамически с помошью тегов и циклов.
- Некоторые теги принципиально не работают вне цикла - или, работая, используют только последний пост.
- Под постом в WP можно понимать любой повторяющийся блок контента. Например, карточка товара - в некотором роде пост. (сомнительно, проверить)
Пример разделения вывода HTML в шаблонах по привязке к ID. Warning! Код очень плохой!
https://pastebin.com/jWe31ggm
https://pastebin.com/jWe31ggm
Pastebin
[PHP] <a class="button_f" href="https://ap - Pastebin.com
Wordpress, продолжение:
- Хуки - это встроенные функции WP, к которым можно "прицеплять" свои, кастомные функции.
Пример использования хука:
add_action('publish_post', 'add_point');
Здесь в роли хука-"крючка" выступает функция "publish post". Срабатывая, она тянет за собой функцию "add_point" - и с публикацией поста выполняется её действие.
Полный список хуков есть в Кодексе.
- Хуки - это встроенные функции WP, к которым можно "прицеплять" свои, кастомные функции.
Пример использования хука:
add_action('publish_post', 'add_point');
Здесь в роли хука-"крючка" выступает функция "publish post". Срабатывая, она тянет за собой функцию "add_point" - и с публикацией поста выполняется её действие.
Полный список хуков есть в Кодексе.
Git
Команда просмотра всех существующих алиасов:
git config --list | grep alias
Команда просмотра всех существующих алиасов:
git config --list | grep alias
Wordpress:
Простое правило: если вместо верстки в кишках шаблона php-код - значит, контент надо редактировать в админке.
Простое правило: если вместо верстки в кишках шаблона php-код - значит, контент надо редактировать в админке.
Функциональное:
Функциональное программирование - удобная методика для построения абстрактного - то есть, универсального кода. Стандартные методы ЯП и библиотек содержат примеры выгод ФП. Вместо написания кода под каждую конкретную задачу мы используем абстрактные функции. ООП тоже может - и должно - содержать абстрагирование, но в ФП реализовать её иногда быстрее и проще.
- Предикаты - это функции, возвращающие true или false.
- Компараторы - функции, возвращающие диапазон значений: -1, 0, 1
- Аппликативы - функции, которые принимают данные и другие функции, после чего применяют эти функции к данным.
Примеры - методы массивов .map, .reduce и другие.
Функциональное программирование - удобная методика для построения абстрактного - то есть, универсального кода. Стандартные методы ЯП и библиотек содержат примеры выгод ФП. Вместо написания кода под каждую конкретную задачу мы используем абстрактные функции. ООП тоже может - и должно - содержать абстрагирование, но в ФП реализовать её иногда быстрее и проще.
- Предикаты - это функции, возвращающие true или false.
- Компараторы - функции, возвращающие диапазон значений: -1, 0, 1
- Аппликативы - функции, которые принимают данные и другие функции, после чего применяют эти функции к данным.
Примеры - методы массивов .map, .reduce и другие.
PHP:
Есть четыре схожих метода подключения внешних файлов:
include
include_once
require
require_once
Различия:
1. require прекращает выполнение скрипта, если подключаемый файл отсутствует, include - нет;
2. постфикс once позволяет включить файл только один раз, сколько бы вызовов не осуществлялось - это удобно, когда во включаемом файле имеется определение фукнций, так как повторное их определение приведёт к ошибке. То есть, это дополнительный уровень устойчивости: случайное подключение несколько раз одного файла будет проигнорировано.
Для критически важных файлов нужно использовать require.
Классы, в частности, подключаются через require_once.
В построении многостраничников без CMS именно так подключаются статические части страниц - хедеры, футеры и т.д.
В HTML-препроцессорах реализован такой же функционал. Как и любая шаблонизация, он сокращает время разработки: правки вносятся в один подключаемый файл вместо статики для множества отдельных страниц.
Есть четыре схожих метода подключения внешних файлов:
include
include_once
require
require_once
Различия:
1. require прекращает выполнение скрипта, если подключаемый файл отсутствует, include - нет;
2. постфикс once позволяет включить файл только один раз, сколько бы вызовов не осуществлялось - это удобно, когда во включаемом файле имеется определение фукнций, так как повторное их определение приведёт к ошибке. То есть, это дополнительный уровень устойчивости: случайное подключение несколько раз одного файла будет проигнорировано.
Для критически важных файлов нужно использовать require.
Классы, в частности, подключаются через require_once.
В построении многостраничников без CMS именно так подключаются статические части страниц - хедеры, футеры и т.д.
В HTML-препроцессорах реализован такой же функционал. Как и любая шаблонизация, он сокращает время разработки: правки вносятся в один подключаемый файл вместо статики для множества отдельных страниц.
PHP - тонкости редиректа:
1. На странице, с которой происходит редирект, продолжается выполнение кода. Если нужно прекратить это - после header() вызываем die или exit.
2. Задержка редиректа делается через аргумент header( refresh: <значение> ).
3. Для редиректа на локальные файлы не обязательно писать полный URL - хватит пути к файлу в директории.
4. Заголовки нужно отправлять до вывода любого контента на страницы.
5. Редирект на шаблон 404 и установка кода ответа тоже делается через header:
<? header("HTTTP/1.0 404 Not Found") ?>
1. На странице, с которой происходит редирект, продолжается выполнение кода. Если нужно прекратить это - после header() вызываем die или exit.
2. Задержка редиректа делается через аргумент header( refresh: <значение> ).
3. Для редиректа на локальные файлы не обязательно писать полный URL - хватит пути к файлу в директории.
4. Заголовки нужно отправлять до вывода любого контента на страницы.
5. Редирект на шаблон 404 и установка кода ответа тоже делается через header:
<? header("HTTTP/1.0 404 Not Found") ?>
PHP - заметки по ООП:
- Три поля видимости значений и методов:
public
protected
private
Они записываются перед названиями сущностей, и назначение их достаточно понятно из названий. Protected отличается от Private тем, что дает более широкий доступ к защищенному свойству - из подкласса. Однако защищенные свойства можно вызывать с помощью методов.
- Конструктор в PHP выглядит как метод __conctruct. Он вызывается при создании экземпляра класса автоматически и принимает аргументы, переопределяющие дефолтные значения. Благодаря нему можно сократить код, передавая значения не присвоением "ключ-значение" в программе, а через скобки при объявлении нового экземпляра.
Плохо:
$serial_first = new Eva();
$serial_first -> $height = 12;
$serial_first -> $weapon = 'knife';
$serial_first -> $autonomy_min = 30;
Хорошо:
$serial_first = new Eva(12, 'knife', 30)
Можно использовать аналогично конструктору обычную функцию, но это не pest practice.
- По аналогии с конструктором есть __destruct - метод, автоматически вызываемый при удалении всех ссылок на объект в коде (и, следовательно, самого объекта). На практике он используется для управления памятью и выноса связанных с уничтожением класса процедур в автоматический метод, чтобы не думать о них при написании остального содержимого.
- Три поля видимости значений и методов:
public
protected
private
Они записываются перед названиями сущностей, и назначение их достаточно понятно из названий. Protected отличается от Private тем, что дает более широкий доступ к защищенному свойству - из подкласса. Однако защищенные свойства можно вызывать с помощью методов.
- Конструктор в PHP выглядит как метод __conctruct. Он вызывается при создании экземпляра класса автоматически и принимает аргументы, переопределяющие дефолтные значения. Благодаря нему можно сократить код, передавая значения не присвоением "ключ-значение" в программе, а через скобки при объявлении нового экземпляра.
Плохо:
$serial_first = new Eva();
$serial_first -> $height = 12;
$serial_first -> $weapon = 'knife';
$serial_first -> $autonomy_min = 30;
Хорошо:
$serial_first = new Eva(12, 'knife', 30)
Можно использовать аналогично конструктору обычную функцию, но это не pest practice.
- По аналогии с конструктором есть __destruct - метод, автоматически вызываемый при удалении всех ссылок на объект в коде (и, следовательно, самого объекта). На практике он используется для управления памятью и выноса связанных с уничтожением класса процедур в автоматический метод, чтобы не думать о них при написании остального содержимого.
PHP - мелочи:
- Для вывода сложных конструкций, а-ля вызов свойства или метода объекта в PHP, недостаточно двойных кавычек. Используется фигурный синтаксис, как в ES6.
- This записывается через знак доллара, и в целом работает как аналог из JS.
- Static - поле, указывающее, что метод или свойство могут быть использованы в контексте самого класса. То есть, для работы с ними не нужно создавать экземпляр объекта класса: просто подключаем класс и вызываем методы. Одно из преимуществ подхода - экономия памяти.
- Для работы со статическими методами классов пользуются вместо this конструкцией "self:: $staticVariableName".
- Cоответственно, self указывает на класс, а this - на экземпляр класса.
- Статические методы тоже выводятся через ::.
- Есть подход, полностью основанный на статических свойствах и методах. Его иногда называют "Классово-ориентированное программирование".
- В PHP есть константы. Записываются они, как и в JS, через const, и не требуют доллара перед именем. Они пишутся в верхнем регистре.
- Оператор .= это сокращенная конкатенация:
$a .= $b // $a = $a . $b
- Для вывода сложных конструкций, а-ля вызов свойства или метода объекта в PHP, недостаточно двойных кавычек. Используется фигурный синтаксис, как в ES6.
- This записывается через знак доллара, и в целом работает как аналог из JS.
- Static - поле, указывающее, что метод или свойство могут быть использованы в контексте самого класса. То есть, для работы с ними не нужно создавать экземпляр объекта класса: просто подключаем класс и вызываем методы. Одно из преимуществ подхода - экономия памяти.
- Для работы со статическими методами классов пользуются вместо this конструкцией "self:: $staticVariableName".
- Cоответственно, self указывает на класс, а this - на экземпляр класса.
- Статические методы тоже выводятся через ::.
- Есть подход, полностью основанный на статических свойствах и методах. Его иногда называют "Классово-ориентированное программирование".
- В PHP есть константы. Записываются они, как и в JS, через const, и не требуют доллара перед именем. Они пишутся в верхнем регистре.
- Оператор .= это сокращенная конкатенация:
$a .= $b // $a = $a . $b
PHP - наследование:
- Написание __construct в дочернем классе переопределяет унаследованный конструктор.
Первый путь решения - дублировать родительский конструктор.
Второй, более соответствующий принципам ООП - вызов конструктора родителя через parent::__construct(аргументы родителя). Тогда конструктор дочернего класса сначала вызывает конструктор родителя, а затем свой уникальный код. При этом порядок вызова не важен!
- parent:: также вызывается при переопределении методов:
public function getSomething() {
$out = parent::methodName();
// операции нового класса
}
- Написание __construct в дочернем классе переопределяет унаследованный конструктор.
Первый путь решения - дублировать родительский конструктор.
Второй, более соответствующий принципам ООП - вызов конструктора родителя через parent::__construct(аргументы родителя). Тогда конструктор дочернего класса сначала вызывает конструктор родителя, а затем свой уникальный код. При этом порядок вызова не важен!
- parent:: также вызывается при переопределении методов:
public function getSomething() {
$out = parent::methodName();
// операции нового класса
}
PHP - абстрактные классы:
Такой тип классов - своего рода база, на которой строятся остальные, более конкретные классы. Для них заблокирована возможность создавать новые объекты: их задача - наследование.
В PHP абстрактные классы изолируют полем abstract перед словом class.
Абстрактными могут быть и методы таких классов. Особенность в том, что они не должны содержать реализации - тела метода. Она определяется в дочерних классах.
Области видимости наследуемого абстактного метода с наследующим в дочернем классе должны либо совпадать, либо понижаться по иерархии:
- приватный
- защищенный
- публичный
В наследуемый абстрактный метод можно добавлять новые аргументы, если делать их необязательными:
function method($arg = something)
Неочевидное преимущество абстрактных классов в том, что пока в дочернем методе не реализованы - или хотя бы не объявлены их абстрактные методы, программа будет выбрасывать ошибку. Хрен забудешь!
Такой тип классов - своего рода база, на которой строятся остальные, более конкретные классы. Для них заблокирована возможность создавать новые объекты: их задача - наследование.
В PHP абстрактные классы изолируют полем abstract перед словом class.
Абстрактными могут быть и методы таких классов. Особенность в том, что они не должны содержать реализации - тела метода. Она определяется в дочерних классах.
Области видимости наследуемого абстактного метода с наследующим в дочернем классе должны либо совпадать, либо понижаться по иерархии:
- приватный
- защищенный
- публичный
В наследуемый абстрактный метод можно добавлять новые аргументы, если делать их необязательными:
function method($arg = something)
Неочевидное преимущество абстрактных классов в том, что пока в дочернем методе не реализованы - или хотя бы не объявлены их абстрактные методы, программа будет выбрасывать ошибку. Хрен забудешь!