This tutorial is a part of the Learn everything about Javascript in one course.
Generator function, function can be paused and continued
Generator function:
- is defined like normal function with an additional
*
(function*
). - can be paused and continued up to the next
yield
key word. yield
keyword can return a value (like return but does not finish the function).- when invoked will return a Generator object (is used to control the pause or continue).
// Generator function, function can be paused and continued
function* createGenerator() {
console.log('run to yield 1')
yield { name: 'Bruce' } // 1st pausable point
yield // 2nd pausable point
console.log('run to yield 3')
yield 3 // 3rd pausable point
console.log('finish')
return 'final'
}
// Generator object
const generator = createGenerator() // invoking Generator function will return a Generator object
console.log(generator.next()) // function is paused at the 1st `yield`
// run to yield 1
// { value: { name: 'Bruce' }, done: false }
console.log(generator.next())
// { value: undefined, done: false }, the 2nd `yield` does not return anything
console.log(generator.next()) // { value: 3, done: false }
console.log(generator.next())
// finish
// { value: 'final', done: true }
console.log(generator.next()) // { value: undefined, done: true }
Generator object, object to control to pause and continue Generator function
Method | Return | Example |
---|---|---|
generator.next() |
an object with value , done key:- value: yielded by the yield expression. - done: boolean, true if function finishes. |
{ value: { name: 'Bruce' }, done: false } |
generator.return(val) |
the val and finish the function |
{ value: val, done: true } |
generator.throw(new Error('your message')) |
throw exception within the function and finish the function. This will crash the program. | Error: your message |
// Generator function, function can be paused and continued
function* createGenerator() {
console.log('run to yield 1')
yield { name: 'Bruce' } // 1st pausable point
yield // 2nd pausable point
console.log('run to yield 3')
yield 3 // 3rd pausable point
console.log('finish')
return 'final'
}
// Generator object
const generator = createGenerator() // invoking Generator function will return a Generator object
console.log(generator.next()) // function is paused at the 1st `yield`
// run to yield 1
// { value: { name: 'Bruce' }, done: false }
console.log(generator.return('lala'))
// { value: 'lala', done: true }, the return method return the passed in value and finish the function
console.log(generator.next()) // { value: undefined, done: true }
// Generator function, function can be paused and continued
function* createGenerator() {
console.log('run to yield 1')
yield { name: 'Bruce' } // 1st pausable point
yield // 2nd pausable point
console.log('run to yield 3')
yield 3 // 3rd pausable point
console.log('finish')
return 'final'
}
// Generator object
const generator = createGenerator() // invoking Generator function will return a Generator object
console.log(generator.next()) // function is paused at the 1st `yield`
// run to yield 1
// { value: { name: 'Bruce' }, done: false }
console.log(generator.throw(new Error('your message'))) // Error: your message
High-order function
is function that either:
- accepts other function as an argument.
- returns a function.
Some examples are: function that accepts callback, memoization function, ... It's nothing new to us but the name "high-order function" is worth mentioned here because a lot of documents and blogs refer to this name.
The "arguments" object in function holds all of its arguments
arguments
object within a function:
- available to use within the function.
- contains all arguments passed into that function.
- is an array-like object (have limited methods and properties of array).
// The "arguments" object in function holds all of its arguments
function printAllArguments(a, b, c, d) {
console.log(arguments) // (i)
console.log(arguments[0]) // (ii)
console.log(arguments[1]) // (iii)
console.log(arguments[2]) // (iv)
console.log(arguments.length) // (v)
console.log(a,b,c) // (vi)
}
printAllArguments(1,2,3, 'd')
// [Arguments] { '0': 1, '1': 2, '2': 3, '3': 'd' }, (i)
// 1, (ii)
// 2, (ii)
// 3, (iv)
// 4, (v)
// 1 2 3, (vi)
Spread syntax ...
, spead given value into list
Spread syntax ...
turns array
, string
, object
=> list of arguments
.
// Handy syntax: spread syntax ..., spead given value into list
// spread array to list of arguments: ...array
const arr = [1,2,3, 'd']
console.log(arr) // [ 1, 2, 3, 'd' ]
console.log(...arr) // spread syntax
// 1 2 3 d
// equals to: console.log(arr[0], arr[1], arr[2], arr[3])
// hence "spread"
const arr2 = [...arr, 'a', 'b']
console.log(arr2) // [ 1, 2, 3, 'd', 'a', 'b' ]
function print(a, b, c, d) {
console.log(d)
}
print(...arr) // d
// spread string, ...string
const str = 'abc'
console.log(...str) // a b c
// equals to: console.log(str[0], str[1], str[2])
// spread object, ...object
const obj = {
a: 'b',
c: 1
}
const obj2 = {
...obj, // spread syntax
d: 2
}
console.log(obj2) // { a: 'b', c: 1, d: 2 }
Destructuring assignment syntax to unpack values into distinct variables
Values to destructure can be arrays
or object properties
. Destructuring also called "treeshaking". We do variable assignment at the same time.
// Destructuring assignment syntax to unpack values into distinct variables
// unpack and assign from array
const arr = [1,2,3,'a']
const [,val1,, val3] = arr // destructuring
console.log(val1) // 2
console.log(val3) // a
// unpack and assign from object properties
const obj = {
a: 'b',
'x-y': 1,
c: 'd'
}
const { a, c } = obj // destructuring and assign variable the same names with object key
console.log(a) // b
console.log(c) // d
const {
a:val5,
c: val6,
'x-y': xy,
} = obj // destructuring and assign variable the DIFFERENT names with object key
console.log(val5) // b
console.log(val6) // d
console.log(xy) // 1
Set default argument value for a function
When an argument is missing, the default value is used. When argument is present, default value is ignored.
// Set default argument value for function
// in this function, the default values for a is 1,
// default b is false
// default c is 'abc'
function print(a = 1, b = false, c = 'abc') {
console.log(a)
console.log(b)
console.log(c)
}
print() // no argument present will use default values
// 1
// false
// abc
print(2,2,2) // no default value used
// 2
// 2
// 2
Destructuring and default value for function argument
It's very common that destructuring and default value are used at the same time where we define a function. Here is an example to help you get familiar with this pattern.
// Set default argument value for function
// in this function, the argument passed in is an object, we then:
// 1. destructure it
// 1. give destructured input default values
function print({ a: val1 = 1, b: val2 = {}, c: val3 = false }) {
console.log(val1)
console.log(val2)
console.log(val3)
}
print({}) // no argument present will use default values
// 1
// {}
// false
print({ a: 3, b: { d: 'f'}, c: true}) // no default value used
// 3
// { d: 'f' }
// true
Summary
Generator function
is function which can be paused and continued.High-order function
is function that either accepts other function as an argument and/or returns a function.Spread
,destructuring assignment
anddefault value
syntax are widely used for shorthand.