konekoya
Hi, I'm Joshua, a Front-end dev from is-land system.
Joshua Lin (@konekoya)
Function scope
function sayHello() {
// function body
}try {
throw "myException";
}
catch (e) {
console.log(e);
}
console.log(e); // referenceError*catch has block scope
var num = 10;
When you declare variables without functions, they will end up in the global scope (window object in the browser)
We will cover ES6 const and let later
function printNum() {
var num = 10;
console.log(num); // 10
}
// Invoking the function
printNum();
When declare variables inside function scope, they'll stay in the function scope.
var foo = "bar";
function bar() {
var foo = "baz";
}
function baz(foo) {
foo = "bam";
bam = "yay";
}
bar();
baz();Compilation and Excution
var foo = "bar";
function bar() {
var foo = "baz";
function baz(foo) {
foo = "bam";
bam = "yay";
}
baz();
}
bar();
foo; // ?
bam; // ?
baz(); // ?Try to answer following questions
var d = 24;
function foo(a) {
var b = a * 2;
function bar(c) {
console.log(a, b, c, d);
}
bar(b * 3);
}
foo(2); // 2 4 12 24Scope look-up stops once it finds the first match
(function() {
var foo = "bar";
function bar() {
var foo = "baz";
function baz(foo) {
foo = "bam";
var bam = "yay";
}
baz();
}
})();
foo // ?
Immediately-Invoked Function Expression (IIFE)
Before ES6, this is what we got
var lang = 'JavaScript';
var version = 5;const NAME = 'JavaScript';
const VERSION = 5;
let engine = 'V8'
let year = 2018;
Now, we have these two shiny additions 😎
// Should assign a value when declared
const x; // SyntaxError
const y = 10;
// Can only be declared once in a scope
var y = 50; // SyntaxError
// Cannot be reassigned
y = 20; // TypeError
const arr = [1, 2];
console.log(arr); // [1, 2]
arr.push(20, 9)
console.log(arr); // [1, 2, 20, 9]WAT?? The value is not "immutable" 😱
We can fix it by using Object.freeze 🤔
const arr = [1, 2];
console.log(arr); // [1, 2]
const _arr = Object.freeze(arr);
// Uncaught TypeError
_arr.push(20, 9)
console.log(_arr); // [1, 2]// Can be declare without initializing with a value
let x;
x = 10;
console.log(x); // 10
// Can't be redeclared
let y = 10;
let y = 50; // SyntaxError
// Can reassign a new value
y = 50;
console.log(y);if (true) {
var foo = 'foo';
let bar = 'bar';
const baz = 'baz';
}
console.log(foo); // ?
console.log(bar); // ?
console.log(baz); // ?// Yep, no matter how mmmmmmmany brackets that you have...
{{{{{var insane = 'yes, you are'}}}}}
console.log(insane) // yes, you are 👀// This creates a new block scope, Awesome!
{
let foo = 'bar';
console.log(foo); // bar
}
console.log(foo); // ReferenceError// When nesting, first come, first served
function foo() {
{
const bar = 'baz';
console.log(bar); // baz
}
console.log(bar); // ReferenceError
}
foo();for (var i = 0; i < 10; i++) {
console.log(i); // 0 ~ 9
}
console.log('Accessing here', i) // Accessing here 10The variable i is now available in the upper scope
for (let i = 0; i < 10; i++) {
console.log(i); // 0 ~ 9
}
console.log('Accessing here', i) // ReferenceErrorWith let keyword, the variable is only available in the for loop body 💯
const API_KEY = 'google-map-123kjdsj41';
const API_ROOT = 'https://www.oodata.com.tw/api/v1';
const PI = 3.14;
const module = require('module'); // commonJSUsing const where possible, it is a signal that the identifier won’t be reassigned.
let isActive = false;
// more code ...
isActive = true;
let user = null;
if (isReady) {
user = {
name: 'John',
age: 20
}
}Using let anywhere else, it is a signal that the variable may be reassigned
Never use var, it is now the weakest signal available in JavaScript land. It can be reassign, redeclared. The intent is not clear. And plus the confusing hoisting mechanism ... 🤔
Handy sites for checking ES6 browser support
1. A general way of thinking about how execution contexts work in JavaScript. In order word, it not a real thing, but rather a metaphor.
2. Variables and function declarations are moved to the top of your code 🙃
Consider the following two examples 👀
a = 2;
var a;
console.log(a); // ?console.log(a); // ?
var a = 2;Variables are moved to the top of their scopes
( in this case - the global scope )
var a;
console.log(a);
a = 2;But, in reality. It has two phases(compilation and execution)
There're two ways to declare a function in JS. They almost work the same way. Yep, I mean almost...
// Function Declarations
function foo() {
return `Hi, I'm foo!`;
}
// Function Expressions
var baz = function () {
return `Hi, I'm baz!`;
}foo(); // ?
function foo() {
console.log(`Hi, I'm foo!`);
}
baz(); // ?
var baz = function () {
console.log(`Hi, I'm baz!`);
}Declarations themselves are hoisted, but assignments, even assignments of function expressions, are not hoisted.
Lets behave a bit differently
console.log(foo); // undefined
console.log(baz); // ?
console.log(bar); // ?
var foo = 10;
let baz = 20;
const bar = 30;Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.
Wait, wat??? 🙄🙄🙄
function foo() {
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // closure! 😄function incremental() {
var x = 1;
return function () {
console.log(x++)
}
}
var foo = incremental();
foo(); // closure
foo(); // closurefunction wait(message) {
setTimeout(function timer() {
console.log(message);
}, 1000);
}
wait("Hello, closure!"); // closurefunction addX(x) {
return function (n) {
return n + x;
};
}
const addThree = addX(3);
console.log(addThree(4)); // 7
console.log(addThree(10)); // 13
console.log(addThree(37)); // 40In essence, addX is a function factory — it creates functions which can add a specific value to their argument.
function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log(something);
}
function doAnother() {
console.log(another.join(" ! "));
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log(something);
}
function doAnother() {
console.log(another.join(" ! "));
}
return {
doSomething: doSomething,
doAnother: doAnother
};
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
I use this pattern in My own website 😎😎😎
Let's watch a short video before jumping into our talk today.
JavaScript is a loosely typed or a dynamic language. Variables in JavaScript are not directly associated with any particular value type, and any variable can be assigned (and re-assigned) values of all types:
var foo = 42; // foo is now a number
foo = 'bar'; // foo is now a string
foo = true; // foo is now a boolean Six data types that are primitives except objects
A primitive (primitive value, primitive data type) is data that is not an object and has no methods. In JavaScript, there are 6 primitive data types: string, number, boolean, null, undefined, symbol (new in ECMAScript 2015).
All primitives are immutable, i.e., they cannot be altered. It is important not to confuse a primitive itself with a variable assigned a primitive value. The variable may be reassigned a new value, but the existing value can not be changed in the ways that objects, arrays, and functions can be altered.
Use typeof operator to identify different types
console.log(typeof foo); // undefined
console.log(typeof true); // boolean
console.log(typeof 123); // number
console.log(typeof "foo"); // string
console.log(typeof { a: 1 }); // object
console.log(typeof null); // object... wat?Wait... why typeof null returns an object? 😬
Okay, it's a bug 🐛. And won't be fixed anyway...
Using triple equals to check the null type:
// Use triple equals to check null type
const NULL = null;
console.log(NULL === null); // true 😎
// or
if (NULL === null) {
// do something here...
}
Or use lodash.isNull to check it, although they're doing the exact same thing behind the scene
https://github.com/lodash/lodash/blob/4.17.10/lodash.js#L11948
When using typeof operator, the returning values are always string
console.log(typeof foo === undefined); // false
console.log(typeof foo === 'undefined'); // true
console.log(typeof (typeof true)); // stringTypeof operator returns undefined no matter the given value is declared or not
let x;
console.log(typeof x); // undefined
console.log(typeof y); // undefinedBy konekoya
JavaScript fundamentals talk. Topic including Scope, Hoisting, Closure and some ES6 features.