Categories
JavaScript JavaScript Basics

Great New Features in ES2018

Ever since ES2015 was released, which was a great leap forward in itself, JavaScript has been improving at a fast pace. Every year since then, new features have been added to JavaScript specifications.

Features like new syntax and new methods for building in JavaScript have been added consistently. In ES2016 and 2017, The Object object had methods like Object.values and Object.entries added.

String methods like padStart and padEnd were added in ES2017. async and await, which is a shorthand syntax for chaining promises, were also added in ES2017.

The includes methods for arrays were added in ES2016. ES2018 was another release with lots of new features. With ES2018, the spread syntax is now available for object literals. Rest parameters were also added.

The for await...of loop, which is a loop syntax iterating through promises sequentially, was also added. The SharedArrayBuffer object was added for representing raw binary data that cannot become detached.

A finally function was also added to the Promise object.


Spread Operator in Objects

The spread syntax works by copying the values of the original array, and then inserting them into another array or putting them in the order they appeared in the array as the list of arguments in a function in the same order.

When the spread operator is used with objects, the key-value pairs appear in the same order they appeared in the original object.

With ES2018, the spread operator works with object literals. Then key-value pairs of an object can be inserted into another object with the spread operator.

If there are two objects with the same key that the spread operator is applied to in the same object, the one that’s inserted later will overwrite the one that’s inserted earlier.

For example, if we have the following:

let obj1 = {foo: 'bar', a: 1};  
let obj2 = {foo: 'baz', b: 1};  
let obj3 = {...obj1, ...obj2 }

Then we get {foo: “baz”, a: 1, b: 1} as the value of obj3 because obj1 is spread before obj2. They both have foo as a key in the object.

First foo: 'bar' is inserted by the spread operator to obj3. Then foo: 'baz' overwrites the value of foo after obj2 is merged in since it has the same key, foo, but was inserted later.

This is great for merging objects as we don’t have to loop through the keys and put in the values, which is much more than one line of code.

One thing to note is that we can’t mix the spread operator between regular objects and iterable objects. For example, we will get TypeError if we write the following:

let obj = {foo: 'bar'};  
let array = [...obj];

Rest Operator

The rest operator is a JavaScript operator where we can store an indefinite number of arguments in a function as an array. It looks exactly like the spread operator, which lets us spread entries of an array or a list of key-value pairs of an object into another object.

For example, if we have a function that has a long list of arguments, we can use the rest operator to shorten the list of parameters in a function.

The rest operator is used with the following syntax:

const fn = (a,b,..restOfTheArgs) => {...}

Where restOfTheArgs is an array with the list of arguments other than the first two.

For example, if we want to write a sum function that takes an indefinite list of numbers as arguments and sum up the numbers, we can write:

const sum = (a,b,...otherNums) => {  
  return a + b + otherNums.reduce((x,y)=>x+y, 0);  
}

As we can see, this is very handy for functions that have any list of arguments. Before we had this, we had to use the arguments object available in functions to get a list of arguments. This is not ideal as we allow them to pass in anything into the arguments.

With the rest operator, we have the best of both worlds. We can have some fixed parameters, while the rest stay flexible. This makes functions more flexible than functions with a fixed number of parameters, while having some flexibility of functions that take an indefinite number of arguments.

The arguments object has all the arguments of the function. Also, it’s not a real array, so array functions aren’t available to them. It’s just an object with indexes and keys to denote the argument’s positions.

Methods like sort, map, forEach, or pop cannot be run on the argument’s object. It also has other properties. This creates confusion for programmers. The arguments that are converted to an array with the rest operator do not have these issues, as they are real arrays.

To call the sum function we wrote, we can write:

const result = sum(1,2,3,4,5,6,7,8,9,10);

The result will be 55, since we summed up all the arguments together. otherNums is an array with all the numbers other than 1 and 2.

We can also use the rest operator to destructure a list of arguments into a list of variables. This means that we can convert a list of parameters into an array with the spread operator, and then decompose the array of arguments into a list of variables.

This is very useful as we can get the entries of the array that’s operated on by the rest operator and convert them to named variables. For example, we can write:

const sum = (a,b,...[c,d,e])=> a+b+c+d+e;

This way, we can use the rest operator, but limit the number of arguments that your function accepts. We take the function parameters a and b, and we also take c, d, and e as parameters.

However, it’s probably clearer without using the rest operator since all the parameters are fixed, we can just list the parameters directly.


for await...of

The for await...of loop allows us to create a loop that iterates over a list of promises as well as over the entries of a normal iterables.

It works with iterable objects like arrays, string, argument object, NodeList object, TypedArray, Map, Set, and user-defined synchronous and asynchronous iterable objects.

To use it, we write:

for await (let variable of iterable) {  
  // run code on variable
}

The variable may be declared with const, let, or var, and the iterable is the iterable objects that we are iterating over. We can iterate over asynchronous iterable objects like the following:

const asynNums = {  
  [Symbol.asyncIterator]() {  
    return {  
      i: 6,  
      next() {  
        if (this.i < 20) {  
          return Promise.resolve({  
            value: this.i++,  
            done: false  
          });  
        }
        return Promise.resolve({  
          done: true  
        });  
      }  
    };  
  }  
};

(async () => {  
  for await (let num of asynNums) {  
    console.log(num);  
  }  
})();

We should see 6 to 19 logged. It also works with async generators:

async function* asynNumGenerator() {  
  var i = 6;  
  while (i < 20) {  
    yield i++;  
  }  
}

(async () => {  
  for await (let num of asynNumGenerator()) {  
    console.log(num);  
  }  
})();

We should see the same thing logged. It also works great with promises:

const arr = Array.from({  
  length: 20  
}, (v, i) => i)let promises = [];

for (let num of arr) {  
  const promise = new Promise((resolve, reject) => {  
    setTimeout(() => {  
      resolve(num);  
    }, 100)  
  })  
  promises.push(promise);  
}

(async () => {  
  for await (let num of promises) {  
    console.log(num);  
  }  
})();

As we can see, if we run the code above, we should see 0 to 19 logged sequentially, which means that promises were iterated through in sequence. This is very handy as we never have anything that can iterate through asynchronous code before this loop syntax was introduced.


Promise.finally()

The finally function is added to the Promise object which runs when the promise is settled. That means it runs whenever the promise is fulfilled or rejected.

It takes a callback function that runs whenever the promise is settled. This lets us run code regardless of how a promise ends. Also, this means that we no longer have to duplicate code in the callbacks for then and catch functions.

To use the finally function, we use it as the following:

promise  
.finally(()=>{  
  // run code that when promise is settled  
})

The finally is useful is we want to run code whenever a promise ends like cleanup code or processing after the code ends.

It’s very similar to calling .then(onFinally, onFinally). However, we do not have to declare it twice to make a variable for it and pass it in twice. The callback for the finally function doesn’t take any argument, as there’s no way to determine the status of the promise beforehand.

It’s used for cases when we don’t know what will happen to the promise, so there’s no need to provide any argument. If a promise is fulfilled then the resolved value will be intact after calling the finally function.

For example, if we have:

Promise.resolve(3).then(() => {}, () => {})

This will resolve to undefined, but if we have:

Promise.resolve(3).finally(() => {})

The code above will resolve to 3. Similarly, if the promise if rejected, we get:

Promise.reject(5).finally(() => {})

This will be rejected with the value 5.


SharedArrayBuffer

The SharedArrayBuffer is an object that’s used to represent a fixed-length raw binary data buffer.

It’s similar to the ArrayBuffer object, but we can use it to create views on shared memory. It can’t become detached, unlike an ArrayBuffer. The constructor of it takes the length of the buffer as an argument.

The length is the size in byte for the array buffer to create. It returns a SharedArrayBuffer of the specified size with contents initialized to 0.

Shared memory can be created and updated by multiple workers on the main thread. However, this may take a while until the changes are propagated to all contexts.


Conclusion

With ES2018, we have more handy features to help developers develop JavaScript apps.

The highlights include the spread operator for objects, which let us copy key-value pairs to other objects and the rest operator to let us pass optional arguments.

The for await...of loop lets us iterate through collections of asynchronous code which could never easily be done before.

Categories
Python

Organize Code with Python Functions

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to define and use Python functions.

Functions

A function is a piece of code that we can invoke repeatedly in different places.

It’s defined with the def keyword as follows:

def greet(name):  
  print('Hello', name)

The greet function above has one parameter. We can pass in an argument to set the value of the parameter when we call it.

Functions always start with the def keyword, then the function name, then parentheses and zero or more parameters inside. Then the first line ends with a colon.

The code for the function is indented inside the function block.

For example, we can call greet as follows:

greet('Joe')

Then we see:

Hello Joe

displayed on the screen since we passed in 'Joe' as the argument of the greet function call.

Functions can call other functions. For example, we can write the following code to make our greet function call another function:

def greet(first_name, last_name):  
  print('Hello', full_name(first_name, last_name))

def full_name(first_name, last_name):  
  return '%s %s' % (first_name, last_name)

greet('Jane', 'Smith')

In the code above, our greet function calls the full_name function which returns the full name constructed by combining first_name and last_name .

In the full_name function, we use the return keyword to return the computed result of combining the first_name and last_name parameters into one string.

The function ends whenever we use the return keyword. Nothing below it will run.

Therefore, we can use it as follows to return the values that we want to return conditionally by using multiple return statements as follows:

import random

def crystal_ball(num):  
  if num == 1:  
    return 'It is a great day'  
  elif num == 2:  
    return 'It is a lucky day'  
  elif num == 3:  
    return 'It is an auspicious day'

r = random.randint(1, 4)  
fortune = crystal_ball(r)  
print(fortune)

In the code above, we have if statements to return something whenever the value of num is 1, 2, or 3.

If num is 1, then crystal_ball returns 'It is a great day' .

If num is 2, then crystal_ball returns 'It is a lucky day' .

If num is 3, then crystal_ball returns ‘It is an auspicious day’ .

Once something is returned, crystal_ball function stops running.

We can then assigned the returned value to another variable for storage as we did by writing:

fortune = crystal_ball(r)

Then we printed out the value of fortune .

The None Value

In Python, we have the value None to represent no value. None has the type NoneType .

None has the capital N .

We can use it as a return value of something that shouldn’t have a value.

For example, the print returns None since there’s nothing to return. It just prints a value on the screen.

If we write:

foo = print('Hello!')  
print(None == foo)

In the code above, we should see:

Hello!  
True

printed on the screen since print returns None , so the value that’s assigned to foo would be None .

Therefore, None == foo returns True .

Keyword Arguments

Python functions can have named arguments. This way, we know what values the arguments are set when we’re passing them.

For example, we can pass in named parameters as follows:

def full_name(first_name, last_name):
  return '%s %s' % (first_name, last_name)

print(full_name(first_name='Jane', last_name='Smith'))

In the code, we called full_name by writing:

full_name(first_name='Jane', la_name='Smith')

Now we know that we’re passing 'Jane' as the value of the first_name parameter and 'Smith' as the value of the last_name parameter.

The Call Stack

The call stack is a data structure that tells us what function we’ve called in the order they’re called.

The earliest called function is at the bottom of the stack, and the later ones are higher in the stack.

For example, in the example we have earlier:

def greet(first_name, last_name):
  print('Hello', full_name(first_name, last_name))

def full_name(first_name, last_name):
  return '%s %s' % (first_name, last_name)

greet('Jane', 'Smith')

Our call stack would have the greet function at the bottom and full_name at the top.

Local and Global Scope

Variables that are inside a function has a local scope. It’s only available inside the function and nested function inside it.

They can’t be referenced outside the function.

Anything at the top level of a Python file has global scope.

Variables with global scope can be accessed inside anything located in a lower function like a block or function.

For example, if we have:

x = 1

def show_x():
  print(x)

show_x()

Then we can reference x inside the show_x function as x has global scope.

On the other hand, if we have:

def show_x():  
  x = 1

print(x)

We’ll get an error saying x isn’t defined.

Having scopes lets us narrow down the scope of the code that can cause a bug. We don’t have to search through the whole program to troubleshoot everything.

Conclusion

Functions are used to organize code into reusable pieces. They take parameters and we call them by passing in arguments.

They can return something with the return keyword. Returned values from a function can be assigned to other variables.

Variables inside functions have a local scope. They can’t be accessed from outside the function.

On the other hand, variables at the top level have global scope, which can be accessed inside functions.

Categories
Python

Quick Intro to Python Modules

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to define and use modules to separate large programs into small pieces.

Importing Modules

Most programs are more than a few lines long. This means that they have to split into multiple small pieces for them to be manageable.

Python programs can be split into modules. Each module is a Python program. For example, the math module has math functions and the random module has random number-related functions.

To use Python modules in another module, we have to use the import keyword and the name of the module.

If we want to import more than one module, we can separate the module names by commas.

For example, we can import the random module and then print out a randomly generated number by calling the randrange function as follows:

import random  
print(random.randrange(0, 101, 2))

In the code above, we import the random module and called the randrange function with the start and end numbers of the number we want to generate as the first 2 arguments.

The end number is excluded from the range of numbers that can be generated.

The last argument has the number of steps to skip between the start and end numbers.

The code above will generate an even number in the range of 0 to 100 inclusive.

from import Statements

We can just import one member of a Python module with the from keyword.

For example, we can just import the randrange function from the random module as follows:

from random import randrange  
print(randrange(0, 101, 2))

In the code above, we just import the randrange function instead of the whole module.

But the rest of the logic is the same.

This is more efficient since we didn’t import everything.

Create Our Own Modules

Anything that is at the top level of a Python file can be imported from a Python module.

For example, we can create a module called foo.py as follows:

x = 1

Then in main.py , we can import and use it as follows:

import foo  
print(foo.x)

We should see 1 on the screen since we have x set to 1 and imported it.

The Module Search Path

Python modules are searched in the code directory, the path set as the value of the PYTHONPATH environment variable, and the default directory that’s set when Python is installed.

The dir() Function

The dir function is used to list the members of a Python module.

For example, we can print a list of members of the math module as follows:

import math  
print(dir(math))

Then we get the following on the screen:

['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

We can see the functions that we can call from the array above.

Packages

We can put Python files in directories to organize them into packages.

For example, we can put foo.py in the package folder, add __init__.py to it.

Then we can import and use package’s members as follows:

from package import foo  
print(foo.x)

Importing * From a Package

The asterisk character indicates that we import all the members from a package.

For example, if we write:

from sound.effects import *

we import all the members from the effects module in the sound package.

This is bad practice because the code is inefficient because we import everything. Also, we may have clashing names since we import more members than we’re supposed to.

Import as

We can use the as keyword to import a module with an alias name. This helps us avoid clashes of names from different modules where we have members that have the same name in different modules.

For example, we can write the following code:

import random as r  
print(r.randrange(0, 101, 2))

to import the random module with an alias r and reference that instead of random .

We can also import a member with as an alias as follows:

from random import randrange as rr  
print(rr(0, 101, 2))

We can call rr instead of randrange to call randrange .

Conclusion

We can define and import Python modules by creating a Python code file and then we can import the members of the Python file.

This lets us divide code into small pieces.

Also, we can organize Python modules into packages by putting module files in folders and add __init__.py to each directory.

Categories
JavaScript Vue

Emitting Custom Events with Vue.js

We can emit events with Vue. Events are emitted by child components and are listened to by their parent components.

Emitted can have data that’s sent along with the event emission.

In this article, we’ll look at how to emit custom Vue events with $emit and listen to them in the parent component.

We can emit events in our child component and use the listen to the event and use the emitted data as follows:

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <Foo @foo="bar = $event"></Foo>
      <p>{{bar}}</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js

Vue.component("Foo", {
  methods: {
    emit() {
      this.$emit("foo", "bar");
    }
  },
  template: `<button @click='emit'>Emit</button>`
});

new Vue({
  el: "#app",
  data: {
    bar: ""
  }
});

In the code above, we defined a Foo component with an emit method that emits an event called foo with the payload 'bar'.

Then in our template, we attached a listener to the template where we referenced our Foo component.

This is where we have:

<Foo @foo="bar = $event"></Foo>

We display assigned item in:

<p>{{bar}}</p>

Then when we click Emit, the foo event is emitted with the value 'bar'.

'bar' is assigned to $event. Then it’s set to bar in the parent component and displayed.

Whatever name we set it to, it’ll be the event name that’s used to attach event listeners. There’s no transformation of the names.

Customizing Component v-model

v-model is shorthand for @input and :value together. We can change that since Vue 2.2.0 to make v-model listen to other event names and bind to different props.

We can add the model property to our component so that v-model can listen to the event name and pass in props with names that we specify.

For example, we can write:

Vue.component("Foo", {
  model: {
    prop: "checked",
    event: "change"
  },
  data() {
    return {
      checked: false
    };
  },
  template: `
  <div>
    <label>foo</label>
    <input
      type="checkbox"
      :checked="checked"
      @change="$emit('change', $event.target.checked)"
    >
  </div>
  `
});

new Vue({
  el: "#app",
  data: {
    bar: false
  }
});

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <Foo v-model="bar"></Foo>
      <p>{{bar}}</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

In the code above, we have:

model: {
    prop: "checked",
    event: "change"
}

to specify that the parent’s v-model directive in the parent listens to the change event and pass data for the checkbox into the checked prop.

Now we should see the value of the checkbox displayed in the p tag below the Foo component as we click the checkbox.

Conclusion

We can emit custom events with Vue with the $emit method. It takes the name of the event as the first argument, and the value we want to emit in the second argument.

Then we can listen to the event and get the payload in the parent component.

We can customize v-model by setting the prop that v-model passes the value to and then event it listens to from the child component to set the value of the specified model.

Categories
JavaScript Vue

Create Custom Filters with Vue.js

In a Vue app, we can use filters to transform data in a template to a format that we want to display the items in.

In this article, we’ll look at how to create filters and use them in our template.

Global Filter

We can define a global filter by using the Vue.filter method to define a filter.

Global filters are available in any part of the app.

It takes the name of the filter as the first argument and a function that takes a value and returns the value transformed to something we want as the second argument.

For example, we can define a global filter and use it as follows:

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{date | localeString}}
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js:

Vue.filter("localeString", function(value) {
  if (!value instanceof Date) return "";
  return value.toLocaleString();
});

new Vue({
  el: "#app",
  data: {
    date: new Date()
  }
});

In the code above, we defined a global filter with:

Vue.filter("localeString", function(value) {
  if (!value instanceof Date) return "";
  return value.toLocaleString();
});

It takes a value parameter, checks if it’s a Date instance, and returns value.toLocaleString() if it is to format the date into a date string.

We then used it by writing:

{{date | localeString}}

in our template.

Local Filter

We can define a local filter by adding the filter method to our filters object in our Vue component.

We can write it as follows:

index.js

new Vue({
  el: "#app",
  data: {
    date: new Date()
  },
  filters: {
    localeString(value) {
      if (!value instanceof Date) return "";
      return value.toLocaleString();
    }
  }
});

In the code above, we moved our filter function into the root component. We reference the same way as we did we the global filter.

Filters can be chained. We just have to separate them with pipes. For example, we can write:

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{date | localeString | lowercase}}
    </div>
    <script src="index.js"></script>
  </body>
</html>

index.js:

Vue.filter("localeString", function(value) {
  if (!value instanceof Date) return "";
  return value.toLocaleString();
});

Vue.filter("lowercase", function(value) {
  return value.toLowerCase();
});

new Vue({
  el: "#app",
  data: {
    date: new Date()
  }
});

We should then see our date string in lower case.

Also, we can pass in arguments into filters as follows:

{{ message | filterA('arg1', arg2) }}

Then 'arg1' will be passed in as the second argument and arg2 as the 3rd argument of our filter function.

Conclusion

We can define filters to transform data into a format that we want to displayed in.

They can be defined globally or locally.

They can be chained and they can also pass in arguments.