# ES6+
- The 6 edition of the ECMAScript-262 standard for JavaScript
- Also known as ECMAScript 2015
- Was finalized and published in June 2015
- This added significant new syntax and features
- Native support in most browsers at this time for most features
- Can use a tool like
Babel
to transpile to ES5 for compatibility - New additions are published yearly. Browser support lags behind slightly.
- ES7 or ECMAScript 2016 is widely supported by current major browsers
- https://en.wikipedia.org/wiki/ECMAScript#6th_Edition_-_ECMAScript_2015
- https://kangax.github.io/compat-table/es6/
# ES6 Features
http://es6-features.org/
- ES6 adds some new syntax and features. Some of the bigger changes are:
- Classes
- Block-Scoped Constructs let and const
- Arrow Functions
- Default Parameters
- Rest and Spread Parameters
- Destructuring Assignment
- Template Strings
- Multi-line String
- Maps & Sets
- Modules
- http://kangax.github.io/compat-table/es6/
# JavaScript OOP Patterns
Patterns to implement Object Oriented Programming in JavaScript
We will be looking at a few basic ones:
- Object Literal
- Constructor Function (Constructor Pattern) 构造函数
- Constructor Function with Prototype (Constructor Pattern) 带有原型的构造函数
- Function that returns an object (Factory Pattern) 返回一个对象的函数
- ES6 Classes
# Object Member Visibility With Constructor Function
Public, Private, Privileged
- These are ways we can have private and public members and methods for objects when we model them with the Constructor pattern.
当使用构造函数模式为对象建模时,这些方法可以让对象拥有私有和公共成员和方法。 - Functions and variables assigned in a constructor with the
this
keyword will be publically visible.
用this
在构造函数中赋值的函数和变量将是公开可见的。
Functions and variables assigned normally will be private.
通常分配的函数和变量将是私有的。 - Be careful, the
this
keyword can get bound to thewindow
object so it is common to see avar that = this;
line in the object to bind that to the properthis
.
注意,this
可以绑定到window
对象,因此通常会在对象中看到一个var that = this;
的行,将它绑定到恰当的this
。
http://crockford.com/javascript/private.html
http://robertnyman.com/2008/10/14/javascript-how-to-get-private-privileged-publicand-static-members-properties-and-methods/
function Person(fname, lname) { | |
this.name = "person: " + fname; | |
var fullName = fname + " " + lname; | |
function print() { | |
alert(fullName); | |
} | |
this.render = function(){ | |
print(); | |
}; | |
} | |
var myPerson = new Person("Brian", "Bailey"); |
# ES6 Classes
# class
syntax
- ES6 added a class syntax similar to other languages.
ES6 增加了类似其他语言的class
类语法。 - Just syntactic sugar, still prototypal under the hood.
只是语法糖,实际还是原型 - Constructor is used to setup parameters and set properties.
构造函数用于设置参数和设置属性。
class Song { | |
constructor(title, artist, duration) { | |
this.title = title; | |
this.artist = artist; | |
this.duration = duration; | |
this.isPlaying = false; | |
} | |
start() { | |
this.isPlaying = true; | |
} | |
} |
# Property Accessors 属性访问器
- Classes can have
getter
andsetter
properties/methods
类可以具有getter
和setter
属性 / 方法 - These allow you to add methods that handle class properties when you use dot notation to get or set their value
当使用.
点符号获取或设置类属性的值时,这些方法允许您添加处理类属性的方法
class Song { | |
constructor(title) { | |
this.title = title; | |
} | |
get title() { | |
return this.title; | |
} | |
set title(t) { | |
this.title = "new title: " + t; | |
} | |
} | |
let s = new Song("hello"); | |
s.title; //returns "hello" | |
s.title = "goodbye"; | |
s.title; //now returns "new title: goodbye" |
# Inheritance
- Classes can have inheritance
类可以继承 - Uses the
extends
keyword to define a "subclass"
用extends
关键字定义 "子类" - Still uses prototype inheritance in the background
内部仍使用原型继承
class RockSong extends Song { | |
constructor(title, artist, duration, type) { | |
super(title, artist, duration); | |
this.type = type; | |
} | |
logType() { | |
console.log(this.type); | |
} | |
} |
# Public & static class fields
- Experimental feature not final yet.
实验功能,还没有最终确定。 - Allows you to define class fields outside the constructor.
允许在构造函数外部定义类字段。 - Also allows for a
static
keyword for static fields that are shared on the class
允许为类上共享的静态字段使用static
关键字
class ClassWithPublicAndStaticFields { | |
static staticProperty = 'aValue'; | |
static staticMethod() { | |
return 'static method statements'; | |
} | |
instatceProperty = 'aValue' | |
publicMethod() { | |
return 'public method statement'; | |
} | |
} |
# References
- JavaScript Object Creation Patterns
http://leoasis.github.io/posts/2013/01/24/javascript-object-creation-patterns/ - JavaScript Classes
https://javascript.info/classes
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes - Learning JavaScript Design Patterns Online Book (More in depth patterns)
https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript - Douglas Crockford – Private Member in JavaScript
http://crockford.com/javascript/private.html
Describes public and private members and methods in Constructor pattern - Douglas Crockford - http://www.crockford.com/
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>JavaScript OOP Demo</title> | |
</head> | |
<body> | |
<script> | |
// Object Literal | |
let carLiteral = { | |
door: 4, | |
color: 'black', | |
wheels: 4, | |
start: function(){ | |
console.log('car literal is started'); | |
} | |
}; | |
let carLiteral2 = { | |
door: 2, | |
color: 'blue', | |
wheels: 4, | |
start: function(){ | |
console.log('car literal 2 is started'); | |
} | |
}; | |
// Constructor Function | |
function Car1(doors, color) { | |
this.doors = doors; | |
this.color = color; | |
let miles = 0; | |
let that = this; | |
let report = function(){ | |
console.log('run report'); | |
console.log('Miles: ' + miles); | |
console.log('Doors: ' + that.doors); | |
}; | |
this.start = function(){ | |
console.log('Car with ' + this.doors + ' doors has started.'); | |
console.log('Miles: ' + miles); | |
report(); | |
}; | |
this.addMile = function(){ | |
miles = miles + 1; | |
}; | |
this.runReport = function(){ | |
report(); | |
}; | |
} | |
let c1 = new Car1(2, 'red'); | |
let c2 = new Car1(4, 'blue'); | |
// Constructor Function with Prototype | |
function CarProto(doors, color) { | |
this.doors = doors; | |
this.color = color; | |
let miles = 0; | |
let that = this; | |
let report = function(){ | |
console.log('run report'); | |
console.log('Miles: ' + miles); | |
console.log('Doors: ' + that.doors); | |
}; | |
this.start = function(){ | |
console.log('Car with ' + this.doors + ' doors has started.'); | |
console.log('Miles: ' + miles); | |
report(); | |
}; | |
this.addMile = function(){ | |
miles = miles + 1; | |
}; | |
this.runReport = function(){ | |
report(); | |
}; | |
} | |
CarProto.aClassProp = 'Ford'; | |
CarProto.prototype.run = function(){ | |
console.log('Car with ' + this.doors + ' doors has started.'); | |
this.runReport(); | |
}; | |
let cproto1 = new CarProto(2, 'red'); | |
// Factory Pattern | |
function carFactory(doors, color) { | |
let car = {}; | |
car.doors = doors; | |
car.color = color; | |
car.run = function(){ | |
console.log(this.color + ' Car with ' + this.doors + ' doors is running.'); | |
}; | |
return car; | |
} | |
let cfactory1 = carFactory(4, 'red'); | |
function vehicleFactory(wheels, color) { | |
if (wheels === 2) { | |
let v = new Motocycle(color); | |
return v; | |
} else { | |
return new Car(wheels, color); | |
} | |
} | |
// ES6 Classes | |
class Vehicle { | |
constructor(wheels, doors) { | |
this.wheels = wheels; | |
this._doors = doors; | |
this._miles = 0; | |
} | |
get doors() { | |
console.log('getting _doors value'); | |
return this._doors; | |
} | |
set doors(d) { | |
console.log('setting _doors value'); | |
this._doors = d; | |
} | |
get miles() { | |
return this._miles + ' miles driven'; | |
} | |
set miles(m) { | |
this._miles = m; | |
} | |
get desc(){ | |
return 'Vehicle with ' + this._doors + ' doors and ' + this.wheels + ' wheels'; | |
} | |
run(){ | |
console.log('Vehicle is running'); | |
} | |
start() { | |
console.log('Started Vehicle with ' + this._doors + ' doors.'); | |
} | |
} | |
let v = new Vehicle(4, 4); | |
class Car extends Vehicle { | |
constructor(wheels, doors, color){ | |
super(wheels, doors); | |
this._color = color; | |
} | |
get color() { | |
return this._color; | |
} | |
set color(c) { | |
this._color = c; | |
} | |
start(){ | |
console.log('Started Car with ' + this._doors + ' doors.'); | |
} | |
} | |
let c = new Car(4, 2, 'blue'); | |
class Ford extends Car { | |
constructor(wheels, doors, color, model) { | |
super(wheels, doors, color); | |
this._model = model; | |
} | |
get model(){ | |
return this._model; | |
} | |
set model(m) { | |
this._model = m; | |
} | |
start(){ | |
console.log('Started Ford ' + this.model + ' with ' + this._doors + ' doors.'); | |
} | |
static report(){ | |
console.log('This is a static method you call on the class'); | |
} | |
} | |
let f = new Ford(4, 4, 'red', 'explorer'); | |
class ClassWithPublicFields { | |
wheels = 4; | |
static staticProperty = 'This is a statick property'; | |
report() { | |
console.log('Class public field wheels: ' + this.wheels); | |
} | |
static staticMethod() { | |
console.log('Static Method'); | |
} | |
} | |
let cc = new ClassWithPublicFields(); | |
</script> | |
</body> | |
</html> |
# JavaScript Closure 闭包
A closure is an inner function that has access to the outer (enclosing) function's variables — scope chain
闭包是一个内部函数,它可以访问外部 (封闭) 函数的变量作用域链
- http://javascriptissexy.com/understand-javascript-closures-with-ease/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
- http://www.javascriptkit.com/javatutors/closures.shtml
# JS Scope 作用域
Here are some links to further explain JavaScript Scope.
https://toddmotto.com/everything-you-wanted-to-know-about-javascript-scope/
https://toddmotto.com/understanding-the-this-keyword-in-javascript/
https://toddmotto.com/es6-arrow-functions-syntaxes-and-lexical-scoping/
Remember that when using the
var
keyword to declare a variable there is no block scope, only functional scope.
当使用var
关键字声明变量时,没有块作用域,只有函数作用域ES6 adds two new keywords that declare block scoped constructs
ES6 添加了两个声明块作用域构造的新关键字let
const
let
is similar tovar
but has block scopelet
is the newvar
const
declares an immutable variable that also has block scope. Once the
value is assigned it is fixed and can't be changed.const
声明了一个同样具有块作用域的不可变变量。一旦赋值,它就是固定的,不能更改。
# Arrow Functions
- This is a new syntax to declare a function
这是声明函数的新语法 - Using an arrow function fixes the problems associated with the
this
keyword in some cases.
在某些情况下,使用箭头函数可以修复与this
关键字相关的问题。
Thethis
keyword will have the same value as in the context of the enclosing function.this
关键字的值将与封闭函数的内容中的值相同。
It fixes the problem when creating closures and makes thethat = this
less necessary.
它修复了创建闭包时的问题,并减少了that = this
的必要性。
Not to be used in all cases, see MDN link.
不是在所有情况下都使用 - If the function executes a single statement, it will implicitly return the result of that statement.
如果该函数执行单个语句,它将隐式返回该语句的结果。
function add (a, b) { | |
return a + b | |
} |
const add = (a, b) => a + b; |
# Default Parameters
- Default parameters are parameters to a function that are given some default values in the function declaration.
默认参数是函数的参数,在函数声明中给出了一些默认值。 - The value can be changed when calling the function
调用函数时可以更改该值
const add = (a = 5, b = 6) => { | |
return a + b; | |
} | |
function add(a = 5, b = 6) { | |
return a + b; | |
} |
# Rest Parameter
- You can use the rest prefix of
...
to extract the rest of the args from a function. - This lets you accept unlimited number of parameters and process them dynamically.
- They come in as an array and only has the arguments that were not provided explicitly.
function add(a, b, ...more) { | |
// more variable in this block is an array of as many params that were passed | |
} | |
add(5, 6, 8, 2, 5, 6); |
- Inside the add function more is
[8, 2, 5, 6]
.
# Spread Operator
- Similar to rest parameter in look but functions differently
与 rest 参数在外观上类似,但功能不同 - It spreads out the values of an array or iterable to separate elements
它将数组的值展开,或者用迭代的方式分隔元素 - Uses the
...
before the variable name
var params = ["hello", true, 7]; | |
var other = [1, 2, ...params ]; // results are [1, 2, "hello", true, 7] | |
var val = [1, 2]; | |
function add(a, b) { | |
return a + b | |
} | |
add(...val) // outputs 3 |
# Destructuring
- Destructuring allows you to extract values from arrays and object
析构允许从数组和对象中提取值 - Uses the array brackets or object curly brackets
使用数组括号或对象花括号
let arr = [5, 8, 2, 5]; | |
let [x, y, z, w] = arr; | |
// x is 5, y is 8, z is 2, w is 5 | |
var o = { p: 42, q: true }; | |
var { p, q } = o; | |
// p is 42 and q is true |
Can rename obj
properties to new variable names
可以将 obj
属性重命名为新的变量名
var {p: foo, q: bar} = o; | |
//now foo is 42 and bar is true |
# Template and Multi-line String
- Use the back tick ``` to define and wrap the string.
- This is for both template strings and multi-line strings.
这既适用于模板字符串,也适用于多行字符串。 - With template strings you can then evaluate variables in the string with
${}
var text = `This is a mult line string that | |
continues on to the next line.`; |
var name = 'brian'; | |
var greeting = `Hello ${name}!`; |
# Maps and Sets
- Map
- Holds key-value pairs similar to an object but keeps track of insertion order.
保存类似于对象的键 - 值对,但保持插入顺序的跟踪。
Maps are iterable.
可迭代
Keys don't have to be strings but can be any object.
键值不一定是字符串,但可以是任何对象。 - Set
- Collections of unique values of any data type.
任何数据类型的唯一值的集合。
Sets are iterable and also keep track of insertion order.
可迭代,并且保持插入顺序的跟踪。
A value in a set can only occur once.
集合中的值只能出现一次。
Additional ES6 Resources to review
http://es6-features.org/
https://scotch.io/tutorials/demystifying-es6-classes-and-prototypalinheritance
https://github.com/getify/You-Dont-Know-JS
http://blog.teamtreehouse.com/get-started-ecmascript-6
https://webapplog.com/es6/
https://codeburst.io/es6-tutorial-for-beginners-5f3c4e7960be
https://html5hive.org/es6-and-babel-tutorial/