Алексей Золотых
ES 2017 | Typescript | Dart |
---|---|---|
Я люблю Dart
Критерий | ES2017 | Typescript | Dart |
---|---|---|---|
🦄 | ∞ /347 | 215 | 154 |
📔 | 3/10 | 5/10 | 8/10 |
🐞 | 76🐞 91✓ |
620🐞 2857✓ |
2015🐞 878💩 |
★ | 21 000 | 22 000 | 1 200 |
Коммиты | 8 000 | 17 000 | 47 000 |
Чем больше коммитов, тем больше багов
Требуется Webpack DevOps, опыт работы 5 лет
pub — из коробки
pub — из коробки
Должен существовать один — и, желательно, только один — очевидный способ сделать это.
npm | pub | |
---|---|---|
Разные версии | ✓ | ⛔️ |
Lock зависимостей | ✓ | ✓ |
Способ хранения зависимостей | копии файлов | символьные ссылки |
Размер на диске | 500мб | 600кб |
⟶ проверка типов ⟶ ES5 +
⟶ проверка типов ⟶ ES2017 ⟶ ES5 +
⟶ проверка типов ⟶ 🛵
tree-shaking
math.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
math.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
math.js
export function square(x) {
return x * x;
}
export function cube(x) {
return x * x * x;
}
main.js
import {cube} from './math.js';
console.log(cube(5)); // 125
Выходной файл
console.log(
function(n){return n*n*n}(5)
)
Выходной файл
console.log(
function(n){return n*n*n}(5)
)
А что же Dart?
main: function() {
H.printString("125");
}
async function sleep() {
console.log('before');
var callback = cb => setTimeout(cb);
await new Promise(callback);
console.log('after');
}
async function sleep() {
console.log('before');
var callback = cb => setTimeout(cb);
await new Promise(callback);
console.log('after');
}
async function sleep() {
console.log('before');
var callback = cb => setTimeout(cb);
await new Promise(callback);
console.log('after');
}
async function sleep() {
console.log('before');
var callback = cb => setTimeout(cb);
await new Promise(callback);
console.log('after');
}
Future timer() async {
print('before');
await new Future.delayed(...);
print('after');
}
Future timer() async {
print('before');
await new Future.delayed(...);
print('after');
}
Future timer() async {
print('before');
await new Future.delayed(...);
print('after');
}
Future timer() async {
print('before');
await new Future.delayed(...);
print('after');
}
function* naturalsTo(n: Number): IterableIterator<Number> {
let k = 0;
while(k < n) yield i++;
}
function* naturalsTo(n: Number): IterableIterator<Number> {
let k = 0;
while(k < n) yield i++;
}
interface IterableIterator<T> extends Iterator>T> {
[Symbol.iterator](): IterableIterato>T>
}
interface Iterator<T> {
next(value?: any): IteratorResult<T>
return?(value?: any): IteratorResult<T>
throw?(e?: any): IteratorResult<T>
}
Iterable<int> naturalsTo(n) sync* {
int k = 0;
while (k < n) yield k++;
}
Iterable naturalsDownFrom(n) sync* {
if (n > 0) {
yield n;
for (int i in naturalsDownFrom(n-1)) { yield i; }
}
}
Iterable naturalsDownFrom(n) sync* {
if ( n > 0) {
yield n;
yield* naturalsDownFrom(n-1);
}
}
async function* f(p) {
yield 1;
await p;
yield* [2, 3];
yield* (async function *() {
await p;
yield 4;
})();
}
async function* g() { ... }
async function f() {
for await (const x of g()) {
}
}
Stream asynchronousNaturalsTo(n) async* {
int k = 0;
while (k < n) yield k++;
}
Stream asynchronousNaturalsTo(n) async* {
int k = 0;
while (k < n) yield k++;
}
RxJS — потоки для бедных
За все нужно платить
Про что это?! Array, Object?
Map, Set?
Маp и Set есть в ES2017 и в Typescript
class MyClass {
operator ==(MyClass other) {
// compare this to other
}
operator [](int i) => list[i]; // get
operator []=(int i, int value) => _list[i] = value; // set
}
import 'dart:async';
main() {
foo();
var future;
runZoned(() { // Starts a new child zone (zone #2).
future = new Future(bar).then(baz);
});
future.then(qux);
}
foo() => ...foo-body... // Executed twice (once each in two zones).
bar() => ...bar-body...
baz(x) => runZoned(() => foo()); // New child zone (zone #3).
qux(x) => ...qux-body...
import 'dart:async';
main() {
foo();
var future;
runZoned(() { // Starts a new child zone (zone #2).
future = new Future(bar).then(baz);
});
future.then(qux);
}
foo() => ...foo-body... // Executed twice (once each in two zones).
bar() => ...bar-body...
baz(x) => runZoned(() => foo()); // New child zone (zone #3).
qux(x) => ...qux-body...
import 'package:deferred/hello.dart' deferred as hello;
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}
Деструктуризация в typescript/ES2017
let [firstName, lastName] = ["Alex", "Zolotykh"];
console.log(firstName, lastName); // Alex, Zolotyh
Деструктуризация в Dart
var {x, m*, y} = [5, 2, 3, 1];
assert(x == 5);
assert(y == 1);
assert(m == [2, 3]);
Все или почти все типы написаны!
github.com/typings/typingsМожно написать свое
@JS()
external printOptions(Options options);
@JS()
@anonymous
class Options {
external bool get responsive;
external factory Options({bool responsive});
}
В dart нет arguments
function(){
console.log(arguments);
}
noSuchMethod в Dart
class MyClass {
noSuchMethod(String name, List args){
print('$name, ${args.length}')
}
}
Можно использовать Flow
interface Conference {
method2();
}
class HolyJS implements Conference {
method2() {
console.log(3);
}
}
var HolyJS = (function () {
function HolyJS() {...}
HolyJS.prototype.method = function () {...};
// Фиг вам! А не интерфейс
return HolyJS;
}());
abstract class Conference { void method(); }
class HolyJS implements Conference {
void method(){ print('Hahaha!');}
}
void main(){
var holy2017 = new HolyJS();
print(holy2017 is Conference);
}
H.printString("true");
Non-Nullable Types (Typescript/Flow)
let name: string;
name = "Marius"; // OK
name = null; // OK
name = undefined; // OK
Typescript (--strictNullChecks)
// Compiled with --strictNullChecks
let name: string;
name = "Marius"; // OK
name = null; // Error
name = undefined; // Error
Typescript (--strictNullChecks)
let name: string | null;
name = "Marius"; // OK
name = null; // OK
name = undefined; // Error
Чем ответит Dart?
Null-aware операторы
exp ?? otherExp
((x) => x == null ? otherExp : x)(exp)
obj ??= value
((x) => x == null ? obj = value : x)(obj)
obj?.method()
((x) => x == null ? null : x.method())(obj)
obj?.child?.child?.getter
String result;
var tempResult = 1 + 2;
if (tempResult is! String) {
throw "Type Mismatch!!";
} else {
result = tempResult;
}
print(result);
Серьезно!?
Think of dart2js as a real compiler, which can analyze your entire program and make optimizations that you probably can’t or won’t do
We don’t claim that all Dart code will run faster than handwritten JavaScript, when compiled to JavaScript, but we’re working to make the common cases fast.
function convertToFastObject(properties) {
function MyClass() {}
MyClass.prototype = properties;
new MyClass();
return properties;
}
void main() {
List array = new List()
..add(null)
..add(null)
..add(null);
array.forEach((a){print(a);});
}
void main() {
List array = new List()
..add(null)
..add(null)
..add(null);
array.forEach((a){print(a);});
}
void main() {
List array = new List()
..add(null)
..add(null)
..add(null);
array.forEach((a){print(a);});
}
...
main: function() {
var array = [];
array.push(null);
array.push(null);
array.push(null);
C.JSArray_methods
.forEach$1(array, new F.main_closure());
}
...
main: function() {
var array = [];
array.push(null);
array.push(null);
array.push(null);
C.JSArray_methods
.forEach$1(array, new F.main_closure());
},
...
forEach$1: function(receiver, f) {
var end, i;
end = receiver.length;
for (i = 0; i < end; ++i) {
f.call$1(receiver[i]);
if (receiver.length !== end)
throw H.wrapException(new P.ConcurrentModificationError(receiver));
}
},
...
...
forEach$1: function(receiver, f) {
var end, i;
end = receiver.length;
for (i = 0; i < end; ++i) {
f.call$1(receiver[i]);
if (receiver.length !== end)
throw H.wrapException(new P.ConcurrentModificationError(receiver));
}
},
...
[null, null, null]
.forEach((a) => {
console.log(null)
});
[null, null, null]
.forEach((a) => {
console.log(null)
});
void main() {
Map map = new Map();
map[1] = null;
map['1'] = 1;
map[{}] = 2;
map.forEach((a,v){print(v);});
}
...
main: function() {
var map = new H.JsLinkedHashMap(0, null, null, null, null, null, 0);
map.$indexSet(0, 1, null);
map.$indexSet(0, "1", 1);
map.$indexSet(0, P.LinkedHashMap_LinkedHashMap$_empty(), 2);
map.forEach$1(0, new F.main_closure());
},
...
$indexSet: function(_, key, value) {
if (typeof key === "string") { this._addHashTableEntry$3(strings, key, value); }
else if (typeof key === "number") { ... this._addHashTableEntry$3(nums, key, value); }
else { ... // Save anothers }
},