Hey there 👋
I'm back with another entry to this series, so... Javascript right? We all love and hate it, yet have no choice but to use it if we want to create interactive websites (kinda). As a result, many developers know Javascript or have at least used it on some occasion.
Consider this post as a comparison between some common aspects of both JS and Dart applications (like async code, handling lists/arrays).
Table Of Contents
- Entrypoints
- Logging
- Functions
- Boolean checks
- Futures/Promises
- Async/Await
- Maps/Objects
- Running an app
- Learning more
Entrypoints
The first step to creating an app is launching/starting it. In dart, an entry-point function is required for all applications, in contrast to Javascript where it's up to you to define such a function. Note that if you use a framework it might require you to define an entry-point of some sort.
Let's see how Dart does it and then show some examples of how we do that in javascript and some frameworks.
Dart
In dart, all applications are required to start with a main()
function.
void main() {
// Your initial code would go here
}
Flutter
In flutter, we are also required to define a main()
function. But to start the app we must call the runApp()
function. This will bootstrap and start our app:
void main() {
runApp(const MyApp());
}
Javascript
Javascript is not as strict and doesn't force us to write a main
function or any kind of entry-point really. Some might start directly when the script loads, or maybe wait until the page is fully loaded. Others might only start when a button is clicked and so on.
When script loads:
function startHere() {
// Your initial code would go here
}
startHere(); // Called when script is loaded
When page loads:
function startHere() {
// Your initial code would go here
}
document.addEventListener('load', () => {
// Called when the page fully loaded all the HTML and external resources
});
Angular
Angular does not require us to define an entry-point function, but it requires us to create a main
file where we will bootstrap/start our application. That file would look something like this:
// imports...
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
Angular uses TypeScript but it's the same drill.
React Native
React native somewhat forces you to create an entry-point in the form of a React Component.
import React from 'react';
import { Text, View } from 'react-native';
const HelloWorldApp = () => {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center"
}}>
<Text>Hello, world!</Text>
</View>
)
}
export default HelloWorldApp;
Logging
Dart does not offer such a variety of logging possibilities as the Javascript console. We are limited to just a single method print
, without adding external packages (like logger).
Dart
var example = '"I will, I do, I can, I should could do, yeh"';
print('I can only log a single string, but can easily interpolate variables like this: $example');
JavaScript
let example = '"I will, I do, I can, I should could do, yeh"';
console.log('I can only log more than a single string, ', `but can easily interpolate variables like this: ${example}`);
Functions
Javascript
// Regular function
function canFly(player) {
return player.hasWings && !player.isAChicken;
}
// Arrow function
const canRespawn = (player) => player.isInmortal;
Dart
canFly(Player player) {
return player.hasWings && !player.isAChicken;
}
// or specifying the type
bool canFly(Player player) {
return player.hasWings && !player.isAChicken;
}
// Arrow function
bool canRespawn = (Player player) => player.isInmortal;
Boolean checks
In Javascript 0
, null
, undefined
, an empty string (''
) are all evaluated as false
. And 1
and any other non-null
value is evaluated as true
.
Dart only considers the boolean value true
as true. So let's have a close look at how to perform some common checks:
Javascript
let undefinedValue = undefined;
let nullValue = null;
let value = 0;
let emptyString = '';
if(!undefinedValue) return;
if(!nullValue) return;
if(!value) return;
if(!emptyString) return;
-
0
,null
,undefined
, and''
are all being treated asfalse
.
Dart
var nullValue = null;
int value = 0;
String emptyString = '';
if(nullValue == null) return;
if(value == 0) return;
if(emptyString.isEmpty) return;
As you can see, in Dart we must implicitly check if it's a certain value. Nothing is treated as a boolean, except booleans themselves (makes sense).
- We must use the
==
equality operator to implicitly check fornull
,0
, and other values - For empty string we can use the built-in
isEmpty()
method
Futures/Promises
Both Javascript and Dart support single-threaded execution. Javascript offers the Promise object to handle this, while in Dart we use Future
objects. These classes represent the eventual completion or failure of some operation.
We commonly use Futures
and Promises
objects when calling remote APIs via HTTP requests, as they take a long time to complete. Synchronously doing this operation would freeze the application until the operation either fails or completes.
Javascript
function answerOfLife() {
const url = 'https://answeroflife.ai/give-it-to-me';
return fetch(url)
.then(result => result.json());
}
const result = answerOfLife()
.then(result => result.answer)
.catch(error => console.error(error));
Dart
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<Response> answerOfLife() {
const url = 'https://answeroflife.ai/give-it-to-me';
return http.get(url)
.then((response) => jsonDecode(response.body));
}
void main() {
var result = answerOfLife()
.then((response) => response.answer)
.catchError((error) => print(error));
}
Did you know that you can create Web Apps with Flutter?
It seems it's not 100% ready for big scale applications, though it does the job with some work on our part.
Async/Await
If you are familiar with Javascript async/await, Dart is almost exactly the same. We mark the function with the async
keyword, then we can use the await
keyword to wait for promises/futures to complete.
Javascript
function answerOfLife() {
const url = 'https://answeroflife.ai/give-it-to-me';
return fetch(url)
.then(result => result.json());
}
async function main() {
try {
const result = await answerOfLife().then(result => result.answer);
} catch(e) {
console.error(error);
}
}
Dart
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<Response> answerOfLife() {
const url = 'https://answeroflife.ai/give-it-to-me';
return http.get(url)
.then((response) => jsonDecode(response.body));
}
void main() async {
try {
const result = await answerOfLife().then(result => result.answer);
} catch(e) {
print(error);
}
}
Arrays/Lists
Dart handles arrays quite similarly to javascript, with some differences. Let's take a look at some of the most common list operations.
Creating arrays
Dart
// Typed list
List<int> steps = [1, 2, 4, 8, 16, 32, 64];
// Untyped list
List stepsAndBabyNames = [1, 2, 4, 'Jonathan', 8, 'Joseph', 16, 32, 'Tommy', 64];
Javascript
const steps = [1, 2, 4, 8, 16, 32, 64];
const stepsAndBabyNames = [1, 2, 4, 'Jonathan', 8, 'Joseph', 16, 32, 'Tommy', 64];
Iterating arrays
Dart
// Using for-in loop
for(var step in steps) {
print('Step: $step');
}
// Clasic for
for(int i = 0; i < steps.length; i++) {
print('Step: ${steps[i]}');
}
// forEach
steps.forEach((step) => print('Step: $step'));
Javascript
// Using for-in loop
for(let step in steps) {
console.log(`Step: ${step}`);
}
// Clasic for
for(let i = 0; i < steps.length; i++) {
console.log(`Step: ${steps[i]}`);
}
// forEach
steps.forEach((step) => console.log(`Step: $step`));
Map items
Dart
steps = steps.map((step) => step * step).toList();
In dart we need to call
toList
to convert back to a List, as map returns a lazy Iterable (docs))
Javascript
steps = steps.map((step) => step * step);
Filter items
Dart
steps = steps.where((step) => step > 16).toList();
Javascript
steps = steps.filter((step) => step > 16);
Get a part of the list
Dart
steps.sublist(2, 4);
Javascript
steps.splice(2, 4);
Item exists
Dart
steps.contains(16);
Javascript
steps.indexOf(16) != -1;
steps.includes(16);
Find index of item
Dart
steps.indexOf(16);
Javascript
steps.indexOf(16);
Find single item
Dart
steps.firstWhere((step) => step == 16);
Javascript
steps.find((step) => step == 16).toList();
Has items
Dart
steps.isNotEmpty;
Javascript
steps.length > 0;
Maps/Objects
Most languages offer some sort of data structure to create unstructured data, dart is not different and offers the Map type.
Creating maps
Dart
Map<String, dynamic> info = {
'name': 'Samuel',
'age': 27,
};
Javascript
const info = {
name: 'Samuel',
age: 27,
};
Serializing/Deserializing JSON
Dart
import 'dart:convert';
Map<String, dynamic> info = {
'name': 'Samuel',
'age': 27,
};
var encodedString = json.encode(info);
var decodedMap = json.decode(infoString);
Javascript
const info = {
name: 'Samuel',
age: 27,
};
const encodedString = JSON.stringify(info);
const decodedMap = JSON.parse(infoString);
Running an app
Running apps differs from language to language, and from framework to framework.
Flutter
Let's first see how we do it in flutter:
- Using the run utility in the IDE
- Executing
flutter run
in the project root
React Native
In react native we:
- use npm script
npm run
- or yarn
npm run
Angular
- Run
ng serve
in the project root - Execute
npm start
Learning more
Summary
As seen in the post, Javascript and Dart have quite a few things in common. But differ in some aspects, such as handling booleans or working with arrays. This post just scratches the surface so let me know if you would like a follow-up!
If you found this post useful, please consider checking my previous post. It's a similar format to this one but comparing the theming/styling aspects of Flutter against CSS.
And as always, thanks for reading. And remember to comment if you have any suggestions, doubts, or something you would like me to cover in these posts.