ECMAScript и все-все-все — различия между версиями
Материал из YourcmcWiki
(Новая страница: «<slideshow title="" style="custis" scaled="true" font="Segoe UI, cursive" headingmark="@@" centermark="%%" incmark="++" subfooter="ECMAScript и все-все-в…») |
м |
||
Строка 1: | Строка 1: | ||
− | <slideshow title="" style=" | + | <slideshow title="" style="nobook" scaled="true" font="Segoe UI, cursive" headingmark="@@" centermark="%%" incmark="++" subfooter="ECMAScript и все-все-все" footer="" /> |
== ECMAScript - ассемблер будущего,<br /> бэкенд, фронтенд и все-все-все @@ %% == | == ECMAScript - ассемблер будущего,<br /> бэкенд, фронтенд и все-все-все @@ %% == | ||
Строка 30: | Строка 30: | ||
<s>JavaScript</s>ECMAScript | <s>JavaScript</s>ECMAScript | ||
* Скриптота! (динамический язык) | * Скриптота! (динамический язык) | ||
+ | * Объект/массив/скаляр (JSON) | ||
* Прототипы, замыкания, колбэки, нет многопоточности | * Прототипы, замыкания, колбэки, нет многопоточности | ||
* ES - язык. А ещё есть окружение (DOM, BOM) | * ES - язык. А ещё есть окружение (DOM, BOM) | ||
Строка 46: | Строка 47: | ||
* Статические... ну, что-то есть... D, Rust, Go, Vala, Swift... | * Статические... ну, что-то есть... D, Rust, Go, Vala, Swift... | ||
*: ''но кто на них пишет-то?'' | *: ''но кто на них пишет-то?'' | ||
+ | * Удобно: легко работать с данными, дженерики не нужны | ||
== Все хотят одного @@ == | == Все хотят одного @@ == | ||
Строка 65: | Строка 67: | ||
* Мощно развивается | * Мощно развивается | ||
− | == Синтаксис @@ == | + | == Синтаксис @@ %% == |
== Perl @@ == | == Perl @@ == | ||
+ | |||
+ | <code-perl> | ||
+ | if ($single) | ||
+ | { | ||
+ | # Single bug | ||
+ | my ($id) = list $ARGS->{id}; | ||
+ | push @bugs, Bugzilla::Bug->check($id); | ||
+ | if (defined $ARGS->{mark}) | ||
+ | { | ||
+ | foreach my $range (split ',', $ARGS->{mark}) | ||
+ | { | ||
+ | if ($range =~ /^(\d+)-(\d+)$/) | ||
+ | { | ||
+ | foreach my $i ($1..$2) | ||
+ | { | ||
+ | $marks{$i} = 1; | ||
+ | } | ||
+ | } | ||
+ | elsif ($range =~ /^(\d+)$/) | ||
+ | { | ||
+ | $marks{$1} = 1; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </code-perl> | ||
== PHP @@ == | == PHP @@ == | ||
+ | |||
+ | <code-php> | ||
+ | $isExact = []; | ||
+ | foreach ([ 'line' => 'l', 'cfo' => 'cc' ] as $k => $t) | ||
+ | { | ||
+ | if (!isset($specified[$k.'_id']) && !isset($specified[$k.'_id_exact']) && | ||
+ | !isset($groups[$k]) && !isset($groups[$k.'_all'])) | ||
+ | $isExact[] = "$posAlias.${k}_id IS NULL"; | ||
+ | elseif ($lastgrp == $k.'all') | ||
+ | $isExact[] = "$posAlias.${k}_id=$t.id"; | ||
+ | } | ||
+ | foreach ([ 'party', 'account', 'paytype' ] as $k) | ||
+ | if (!isset($specified[$k.'_id']) && !isset($groups[$k])) | ||
+ | $isExact[] = "$posAlias.${k}_id IS NULL"; | ||
+ | return implode(' AND ', $isExact) ?: '1=1'; | ||
+ | </code-php> | ||
+ | |||
+ | * Что за $$$$$? | ||
== Python @@ == | == Python @@ == | ||
+ | |||
+ | <code-python> | ||
+ | class FileCache: | ||
+ | def __init__(self, dir): | ||
+ | self.dir = dir | ||
+ | if not os.path.isdir(dir): | ||
+ | os.mkdir(dir) | ||
+ | def fn(self, key): | ||
+ | key = re.sub('([^a-zA-Z0-9_\-]+)', lambda x: binascii.hexlify(x.group(1)), key) | ||
+ | return self.dir+'/'+key | ||
+ | def clean(self): | ||
+ | t = time.time() | ||
+ | for fn in os.listdir(self.dir): | ||
+ | if t > os.stat(self.dir+'/'+fn).st_mtime: | ||
+ | os.unlink(self.dir+'/'+fn) | ||
+ | </code-python> | ||
+ | |||
+ | * Пробелы меняют смысл?!!!! | ||
== Ruby @@ == | == Ruby @@ == | ||
+ | |||
+ | <source lang="ruby"> | ||
+ | module Gitlab | ||
+ | class SearchResults | ||
+ | attr_reader :current_user, :query | ||
+ | |||
+ | def objects(scope, page = nil) | ||
+ | case scope | ||
+ | when 'projects' | ||
+ | projects.page(page).per(per_page) | ||
+ | when 'issues' | ||
+ | issues.page(page).per(per_page) | ||
+ | when 'merge_requests' | ||
+ | merge_requests.page(page).per(per_page) | ||
+ | when 'milestones' | ||
+ | milestones.page(page).per(per_page) | ||
+ | else | ||
+ | Kaminari.paginate_array([]).page(page).per(per_page) | ||
+ | end | ||
+ | end | ||
+ | </source> | ||
+ | |||
+ | * projects - переменная? Фигвам. Метод без аргументов.) | ||
== Go @@ == | == Go @@ == | ||
+ | |||
+ | <source lang="go"> | ||
+ | func TestChannelStoreSave(t *testing.T) { | ||
+ | Setup() | ||
+ | |||
+ | teamId := model.NewId() | ||
+ | |||
+ | o1 := model.Channel{} | ||
+ | o1.TeamId = teamId | ||
+ | o1.DisplayName = "Name" | ||
+ | o1.Name = "a" + model.NewId() + "b" | ||
+ | o1.Type = model.CHANNEL_OPEN | ||
+ | |||
+ | if err := (<-store.Channel().Save(&o1)).Err; err != nil { | ||
+ | t.Fatal("couldn't save item", err) | ||
+ | } | ||
+ | |||
+ | if err := (<-store.Channel().Save(&o1)).Err; err == nil { | ||
+ | t.Fatal("shouldn't be able to update from save") | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | * Что за смайлики <tt><nowiki>:= <- & *</nowiki></tt>? Где мои скобочки? | ||
== Erlang @@ == | == Erlang @@ == | ||
+ | |||
+ | <source lang="erlang"> | ||
+ | iq_handler(From, _To, | ||
+ | #iq{type=set, lang = Lang, | ||
+ | sub_el = #xmlel{name = Operation} = SubEl} = IQ, CC)-> | ||
+ | ?DEBUG("carbons IQ received: ~p", [IQ]), | ||
+ | {U, S, R} = jid:tolower(From), | ||
+ | Result = case Operation of | ||
+ | <<"enable">>-> | ||
+ | ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]), | ||
+ | enable(S,U,R,CC); | ||
+ | <<"disable">>-> | ||
+ | ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]), | ||
+ | disable(S, U, R) | ||
+ | end, | ||
+ | case Result of | ||
+ | ok -> | ||
+ | ?DEBUG("carbons IQ result: ok", []), | ||
+ | IQ#iq{type=result, sub_el=[]}; | ||
+ | {error,_Error} -> | ||
+ | ?ERROR_MSG("Error enabling / disabling carbons: ~p", [Result]), | ||
+ | Txt = <<"Database failure">>, | ||
+ | IQ#iq{type=error,sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]} | ||
+ | end; | ||
+ | </source> | ||
+ | |||
+ | * Ой-ой-ой | ||
+ | * Классов нет, есть процессы | ||
== OCaml O_O @@ == | == OCaml O_O @@ == | ||
− | == | + | <source lang="ocaml"> |
+ | let log_client_info c sock = | ||
+ | let buf = Buffer.create 100 in | ||
+ | let date = BasicSocket.date_of_int (last_time ()) in | ||
+ | Printf.bprintf buf "%-12s(%d):%d -> %-30s[%-14s %-20s] connected for %5d secs %-10s bw %5d/%-5d %-6s %2d/%-2d reqs " | ||
+ | (Date.simple date) | ||
+ | (nb_sockets ()) | ||
+ | (client_num c) | ||
+ | ( | ||
+ | let s = c.client_name in | ||
+ | let len = String.length s in | ||
+ | if len > 30 then String.sub s 0 30 else s) | ||
+ | |||
+ | (brand_to_string c.client_brand) | ||
+ | (match c.client_kind with Indirect_address _ | Invalid_address _ -> "LowID" | ||
+ | | Direct_address (ip,port) -> Printf.sprintf "%s:%d" | ||
+ | (Ip.to_string ip) port) | ||
+ | (last_time () - c.client_connect_time) | ||
+ | (if c.client_rank > 0 then | ||
+ | Printf.sprintf "rank %d" c.client_rank | ||
+ | else "") | ||
+ | (nwritten sock) (nread sock) | ||
+ | (if c.client_banned then "banned" else "") | ||
+ | c.client_requests_received | ||
+ | c.client_requests_sent | ||
+ | ; | ||
+ | </source> | ||
+ | * ПОЛИЗ?!!!! | ||
+ | |||
+ | == JS @@ == | ||
+ | <source lang="javascript> | ||
+ | TreeGridNode.prototype.setChildren = function(isLeaf, newChildren) | ||
+ | { | ||
+ | if (!this.tr) | ||
+ | this.grid.tbody.innerHTML = ''; | ||
+ | else | ||
+ | { | ||
+ | var tr = this.tr[this.tr.length-1]; | ||
+ | while (tr.nextSibling && tr.nextSibling._node.level > this.level) | ||
+ | this.grid.tbody.removeChild(tr.nextSibling); | ||
+ | if (this.leaf != isLeaf) | ||
+ | { | ||
+ | if (isLeaf) | ||
+ | { | ||
+ | this.tr[0].cells[0].firstChild.className = 'collapser collapser-inactive'; | ||
+ | removeListener(this.tr[0].cells[0].firstChild, 'click', this._getToggleHandler()); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | this.tr[0].cells[0].firstChild.className = this.collapsed ? 'collapser collapser-collapsed' : 'collapser collapser-expanded'; | ||
+ | addListener(this.tr[0].cells[0].firstChild, 'click', this._getToggleHandler()); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | this.leaf = isLeaf; | ||
+ | this.children = []; | ||
+ | this.childrenByKey = {}; | ||
+ | this.addChildren(newChildren); | ||
+ | } | ||
+ | </source> | ||
[[Категория:VitaliPrivate]] | [[Категория:VitaliPrivate]] |
Версия 12:04, 10 октября 2016
- Автор
- Виталий Филиппов
- Дополнительный нижний колонтитул
- ECMAScript и все-все-все
Содержание
- 1 ECMAScript - ассемблер будущего, бэкенд, фронтенд и все-все-все @@ %%
- 2 О своих предпочтениях @@
- 3 О чём доклад? @@
- 4 Что такое JS? @@
- 5 Скриптота vs типизация @@
- 6 Но тема-то серьёзная @@
- 7 Все хотят одного @@
- 8 Почему JS? @@
- 9 Синтаксис @@ %%
- 10 Perl @@
- 11 PHP @@
- 12 Python @@
- 13 Ruby @@
- 14 Go @@
- 15 Erlang @@
- 16 OCaml O_O @@
- 17 JS @@
ECMAScript - ассемблер будущего,
бэкенд, фронтенд и все-все-все @@ %%
(Об эволюции и фичах JavaScript)
Виталий Филиппов, CUSTIS
О своих предпочтениях @@
«И давно вы занимаетесь программизмом?»
- Начинал лет в 11 с C/C++ (Turbo C / C++Builder)
- Потом открыл для себя Linux, свободный софт...
- главное читать логи :)
- ...LAMP (Perl/PHP), HTML и JS
- Теперь полюбил серверный JS (nodejs)
О чём доклад? @@
- Почему JS?
- История JavaScript
- Обзор языка, производительность
- Обзор выдумок
- (фреймворки, системы сборки и т.п)
- Немного демо
Что такое JS? @@
JavaScriptECMAScript
- Скриптота! (динамический язык)
- Объект/массив/скаляр (JSON)
- Прототипы, замыкания, колбэки, нет многопоточности
- ES - язык. А ещё есть окружение (DOM, BOM)
- Куча новых фич (ES2015-2016-2017)
- Браузерный - Chrome (V8), Firefox (SpiderMonkey) и даже IE (ChakraCore)
- Серверный - node.js (V8)
Скриптота vs типизация @@
Но тема-то серьёзная @@
- ХОЛИВАР!!!
- Скриптота развивается - много популярных языков
- Статические... ну, что-то есть... D, Rust, Go, Vala, Swift...
- но кто на них пишет-то?
- Удобно: легко работать с данными, дженерики не нужны
Все хотят одного @@
- Типизация - не необходимость, а лишь один из способов проверки
- ещё есть Rust = borrow checker
- ещё есть функциональщина = по сути "purity" checker
- auto уже даже в C++
- тайпчекер (частично) уже даже в PHP (+ Hack)
Почему JS? @@
- Нейтральный C-подобный синтаксис
- Быстрые интерпретаторы
- Событийная машина
- Мощно развивается
Синтаксис @@ %%
Perl @@
if ($single) { # Single bug my ($id) = list $ARGS->{id}; push @bugs, Bugzilla::Bug->check($id); if (defined $ARGS->{mark}) { foreach my $range (split ',', $ARGS->{mark}) { if ($range =~ /^(\d+)-(\d+)$/) { foreach my $i ($1..$2) { $marks{$i} = 1; } } elsif ($range =~ /^(\d+)$/) { $marks{$1} = 1; } } } }
PHP @@
$isExact = []; foreach ([ 'line' => 'l', 'cfo' => 'cc' ] as $k => $t) { if (!isset($specified[$k.'_id']) && !isset($specified[$k.'_id_exact']) && !isset($groups[$k]) && !isset($groups[$k.'_all'])) $isExact[] = "$posAlias.${k}_id IS NULL"; elseif ($lastgrp == $k.'all') $isExact[] = "$posAlias.${k}_id=$t.id"; } foreach ([ 'party', 'account', 'paytype' ] as $k) if (!isset($specified[$k.'_id']) && !isset($groups[$k])) $isExact[] = "$posAlias.${k}_id IS NULL"; return implode(' AND ', $isExact) ?: '1=1';
- Что за $$$$$?
Python @@
class FileCache: def __init__(self, dir): self.dir = dir if not os.path.isdir(dir): os.mkdir(dir) def fn(self, key): key = re.sub('([^a-zA-Z0-9_\-]+)', lambda x: binascii.hexlify(x.group(1)), key) return self.dir+'/'+key def clean(self): t = time.time() for fn in os.listdir(self.dir): if t > os.stat(self.dir+'/'+fn).st_mtime: os.unlink(self.dir+'/'+fn)
- Пробелы меняют смысл?!!!!
Ruby @@
module Gitlab class SearchResults attr_reader :current_user, :query def objects(scope, page = nil) case scope when 'projects' projects.page(page).per(per_page) when 'issues' issues.page(page).per(per_page) when 'merge_requests' merge_requests.page(page).per(per_page) when 'milestones' milestones.page(page).per(per_page) else Kaminari.paginate_array([]).page(page).per(per_page) end end
- projects - переменная? Фигвам. Метод без аргументов.)
Go @@
func TestChannelStoreSave(t *testing.T) { Setup() teamId := model.NewId() o1 := model.Channel{} o1.TeamId = teamId o1.DisplayName = "Name" o1.Name = "a" + model.NewId() + "b" o1.Type = model.CHANNEL_OPEN if err := (<-store.Channel().Save(&o1)).Err; err != nil { t.Fatal("couldn't save item", err) } if err := (<-store.Channel().Save(&o1)).Err; err == nil { t.Fatal("shouldn't be able to update from save") }
- Что за смайлики := <- & *? Где мои скобочки?
Erlang @@
iq_handler(From, _To, #iq{type=set, lang = Lang, sub_el = #xmlel{name = Operation} = SubEl} = IQ, CC)-> ?DEBUG("carbons IQ received: ~p", [IQ]), {U, S, R} = jid:tolower(From), Result = case Operation of <<"enable">>-> ?INFO_MSG("carbons enabled for user ~s@~s/~s", [U,S,R]), enable(S,U,R,CC); <<"disable">>-> ?INFO_MSG("carbons disabled for user ~s@~s/~s", [U,S,R]), disable(S, U, R) end, case Result of ok -> ?DEBUG("carbons IQ result: ok", []), IQ#iq{type=result, sub_el=[]}; {error,_Error} -> ?ERROR_MSG("Error enabling / disabling carbons: ~p", [Result]), Txt = <<"Database failure">>, IQ#iq{type=error,sub_el = [SubEl, ?ERRT_INTERNAL_SERVER_ERROR(Lang, Txt)]} end;
- Ой-ой-ой
- Классов нет, есть процессы
OCaml O_O @@
let log_client_info c sock = let buf = Buffer.create 100 in let date = BasicSocket.date_of_int (last_time ()) in Printf.bprintf buf "%-12s(%d):%d -> %-30s[%-14s %-20s] connected for %5d secs %-10s bw %5d/%-5d %-6s %2d/%-2d reqs " (Date.simple date) (nb_sockets ()) (client_num c) ( let s = c.client_name in let len = String.length s in if len > 30 then String.sub s 0 30 else s) (brand_to_string c.client_brand) (match c.client_kind with Indirect_address _ | Invalid_address _ -> "LowID" | Direct_address (ip,port) -> Printf.sprintf "%s:%d" (Ip.to_string ip) port) (last_time () - c.client_connect_time) (if c.client_rank > 0 then Printf.sprintf "rank %d" c.client_rank else "") (nwritten sock) (nread sock) (if c.client_banned then "banned" else "") c.client_requests_received c.client_requests_sent ;
- ПОЛИЗ?!!!!
JS @@
TreeGridNode.prototype.setChildren = function(isLeaf, newChildren) { if (!this.tr) this.grid.tbody.innerHTML = ''; else { var tr = this.tr[this.tr.length-1]; while (tr.nextSibling && tr.nextSibling._node.level > this.level) this.grid.tbody.removeChild(tr.nextSibling); if (this.leaf != isLeaf) { if (isLeaf) { this.tr[0].cells[0].firstChild.className = 'collapser collapser-inactive'; removeListener(this.tr[0].cells[0].firstChild, 'click', this._getToggleHandler()); } else { this.tr[0].cells[0].firstChild.className = this.collapsed ? 'collapser collapser-collapsed' : 'collapser collapser-expanded'; addListener(this.tr[0].cells[0].firstChild, 'click', this._getToggleHandler()); } } } this.leaf = isLeaf; this.children = []; this.childrenByKey = {}; this.addChildren(newChildren); }