● let
● Destructuring Assignments 解構賦值
● 可變參數
● 解構參數
● 解構數組
● 解構對象
● 遍歷
● 快速創建對象
● 只讀變量
● Sets
● Maps
● Symbols
● WeakMaps
● Promises
● 創建類
● Modules
● 內置函數
let
使用let聲明的變量只在語句塊內有效。
"use strict"; function blockBindingDemo(){ let a = 123; var b = 123; if(true){ let a = 456; b = 456; console.log("使用let語句塊中的a為" +a);//456 console.log("使用var語句塊中的b為" +b) } console.log("使用let語句塊外的a為" +a);//123 console.log("使用var語句塊外的b為" +b);//456 } blockBindingDemo();
以上,以let方式聲明的變量只在語句塊內有效,而以var方式的變量是一個全局變量。
variable hoisting
可以先初始化變量,再聲明變量,如下是可以的:
x=6;
var x;
console.log(x);
相當於:
var x;
x = 6;
變量首先得初始化,否則會呈現undefined
var x = 5;
console.log(x + " " + y); //5 undefined
var y = 7;
因為在聲明變量y之前還沒有初始化,y還沒有被hoisted。
Arrow Function, Lambda表達式
在es6之前,通常這樣定義和使用函數:
var helloWorld = function(name, greeting){ return name + " " + greeting; } console.log(helloWorld("darren","hello"));
es6中可以使用Lambda表達式:
var newGreeting = (name, greeting) => { return name + " " + greeting; } console.log(newGreeting("darren","hello"));
還可以簡化成這樣的寫法:
var newGreeting = (name, greeting) => name + " " + greeting; console.log(newGreeting("darren","hello"));
如果只有一個參數,可以寫成:
var greeting = greeting => "Hello " + greeting;
如果沒有參數,可以寫成:
var greeting = () => "Hello Darren";
■ 遍歷一個數組,把數組內的元素變成大寫。
var courses = ['hello','world']; cosnole.log(courses.map(course => { return course.toUpperCase(); }))
■ 對數組排序。
var myArr = [2, 4.6]; var sortedArr = myArr.sort((a, b) => a < b ? 1 : -1); console.log(sortedArr);
■ this的作用域。
function Course(){ this.name = ""; this.description = ""; this.author = ""; this.getSummary = function(){ return this.name + ", " + this.description; }; this.getDetails = fuction(){ window.setTimeout(() => {console.log(this.getSummary() + " " + this.author)},1000); } } var course = new Course(); course.getDetails();
以上,this的作用域指的是Course,而不是window。也就是說,lambda表達式中的this的作用域的指向取決於在哪里定義,而不是取決於在哪里使用。
Destructuring Assignments 解構賦值
es6之前這樣寫:
var x=1,y=2,z=3;
現在可以這樣寫:
var [x, y, z] = [1, 2, 3];
[y,z] =[z,y];
■ 從數組中解構賦值
function getDate(){ return [15,07,2015]; } var [x, y] = getDate(); var [,,z] = getDate(); console.log(x); console.log(y); console.log(z);
■ 從對象中解構賦值
function currentDate(){ return {x:1, y:2, z:3}; } var {y: myy, z: myz} = currentDate(); console.log(myy); console.log(myz);
默認參數值 Default Parameters
es6之前,這樣寫默認參數值:
function sayHi(firstname, lastname){ firstname = firstname || "darren"; lastname = lastname || "ji"; console.log(firstname + " " + lastname); } sayHi();
現在可以這么寫:
function sayHi(firstname="darren",lastname="ji"){ console.log(firstname + " " + lastname); } sayHi();
可變參數
把可變參數拼接成字符串,以前這樣寫:
function joinArgus(){ return Array.prototype.slice.call(arguments).join(' '); } var result = joinArgus('hello','world' ); console.log(result);
現在可以這么寫:
function joinArgus(...words){ return words.join(' '); } var result = joinArgus('',''); console.log(result);
可以結合Spread Operator來處理可變參數。
function logMessages(message, ...args){ console.log(message, ...args); } logMessages("he %s : %s", "","");
解構參數
function logMessage(msg, {name: courseName, publisher: publisherName}){ console.log(msg + " " + courseName + " by " + publisherName); } logMessage("", {name:"",publisher:""});
解構數組
//賦值的時候解構 var numbers = [1, 2, 3, 4, 5]; var [first, second, third, , fifth] = numbers; console.log(fifth); //使用參數的時候解構 function arrayDestructuring([first, second,...rest]){ console.log(first); console.log(second); console.log(rest); } arrayDestructuring(numbers); //嵌套數組的解構 var numbers_nested = [1, 2, [3, 4, 5]]; var [first, second, [third,,fifth]] = numbers_nested; console.log(first); console.log(second); console.log(third);
解構對象
引用如下: browser.min.js <script src="some.js" type="text/babel"></script> "use strict"; var course = { name: "", publisher: "" }; function courseDetails(course){ let {name, publisher} = course; console.log(name + " " + publisher); } courseDetails(course);
遍歷
"use strict"; var words = ['','','']; //輸出鍵和值 for(let word of words.etrieis()){ console.log(word); } //輸出值 for(let word of words.values()){ console.log(word); } //輸出鍵 for(let word of words.keys()){ console.log(word); }
Generators
有以下的一個Generator的寫法:
function* greet(){ console.log(`調用了greet方法`); } greet();
顯示結果:
什么都不顯示
按照以往調用函數的方式調用,結果什么都不顯示。greet()到底是什么呢?不妨打印出一探究竟。
function* greet(){ console.log(`調用了greet方法`); } let greeter = greet(); console.log(greeter);
顯示結果:
{next:[Function], throw:[Function]}
原來,當調用greet()的時候並沒有執行方法,而是返回一個object對象。
既然next是greet()返回結果中的一個函數,那就調用next()。
function* greet(){ console.log(`調用了greet方法`); } let greeter = greet(); let next = greeter.next(); console.log(next);
顯示結果:
調用了greet方法
{value:undefined, done: true}
value:undfined說明還沒有從generator中返回任何值,done:true說明yield已經被執行,這里是null。
yield到底是什么?
function* greet(){ console.log(`調用了greet方法`); yield "hello"; } let greeter = greet(); let next = greeter.next(); console.log(next);
顯示結果:
調用了greet方法
{value:'hello', done: false}
value:'hello'說明yield返回一個hello值, done:false說明yield還沒被執行。如果再執行一次next方法會怎樣?
function* greet(){ console.log(`調用了greet方法`); yield "hello"; } let greeter = greet(); let next = greeter.next(); console.log(next); let done = greeter.next(); console.log(done);
顯示結果:
調用了greet方法
{value:'hello', done: false}
{value:undefined, done:true}
可見,當第一次執行next方法時,yield返回hello,但還沒真正執行yield語句;當第二次執行next方法時,執行了yield語句,value再次變為undefined。
● 多個yield語句
如果有多個yield語句呢?
function* greet(){ console.log(`Generators會延遲加載,第一次調用next方法時執行`); yield "How"; console.log(`第二次調用next方法時執行`); yield "are"; console.log(`第三次調用next方法時執行`); } var greeter = greet(); console.log(greeter.next()); console.log(greeter.next()); console.log(greeter.next());
結果:
Generators會延遲加載,第一次調用next方法時執行
{value: 'How', done:false}
第二次調用next方法時執行
{value: 'are', done:false}
第三次調用next方法時執行
{value: undefined, done:true}
還可以通過遍歷greet()來分別執行。
function* greet(){ console.log(`Generators會延遲加載,第一次調用next方法時執行`); yield "How"; console.log(`第二次調用next方法時執行`); yield "are"; console.log(`第三次調用next方法時執行`); } var greeter = greet(); for(let word of greeter){ console.log(word); }
結果:
Generators會延遲加載,第一次調用next方法時執行
How
第二次調用next方法時執行
are
第三次調用next方法時執行
可見,greet()集合的集合元素是每一個yield的返回值,也就是調用next方法后返回對象中的value字段對應的值。
也就是按如下寫也能獲取相同的返回結果:
function* greet(){ console.log(`Generators會延遲加載,第一次調用next方法時執行`); yield "How"; console.log(`第二次調用next方法時執行`); yield "are"; console.log(`第三次調用next方法時執行`); } var greeter = greet(); console.log(greeter.next().value); console.log(greeter.next().value); console.log(greeter.next().value);
● yield賦值
function* greet(){ let a = yield "first"; console.log(a); yield "second"; } var greeter = greet(); console.log(greeter.next().value); console.log(greeter.next().value);
結果:
first
undefined
second
而預期的結果是:
first
first
second
真實的結果和預期的結果不一樣,yield語句並不能賦值。那么,變量a該如何賦值呢?
function* greet(){ let a = yield "first"; console.log(a); yield "second"; } var greeter = greet(); console.log(greeter.next().value); console.log(greeter.next('給上一個yield中的變量a賦的值').value);
結果:
first
給上一個yield中的變量a賦的值
second
所以,通過next方法可以給上一個yield語句中的變量賦值。
再看一個yield賦值的例子。
function* greet(){ let a = yield "first"; a = yield a + "hello"; yield a + "hello"; } var greeter = greet(); console.log(greeter.next().value); console.log(greeter.next("first").value); console.log(greeter.next("second").value);
結果:
first
firsthello
secondhello
→ 當執行console.log(greeter.next().value);時,把第一個yield的返回結果first打印出來。
→ 當執行console.log(greeter.next("first").value);先把first賦值給上一個yield,即第一個yield中的變量a,打印出firsthello。
→ 當執行console.log(greeter.next("second").value);先把second賦值給上一個yield,即第二個yield中的變量a,打印出secondhello。
String Templates
以前這樣拼接字符串。
var a = "Hello";
var greeting = a + ", World";
console.log(greeting);
ES6中可以這樣寫:
var a = "Hello";
var greeting = `${a} , World`;
console.log(greeting);
在``之內的接受空白、換行等,可以把變量放在${}之內。
var msg = `it's time ${new Date().getHours()}, I'm sleeping`;
console.log(msg);
``之內還可以作為參數傳遞給某個方法並分別取出字符串和變量:
function conclude(strings, ...values){ console.log(strings); console.log(values); } conclude`it's time ${new Date().getHours()} I'm sleeping`;
結果:
it's time , I'm sleeping
20
以上``之內的字符串自動拼接以逗號分隔,``之內變量賦值給 values。
快速創建對象
let firstName = "Darren";
let lastName = "Ji";
let person = {firstName, lastName};
console.log(person);
結果:
{firstName: 'Darren', lastName: 'Ji'}
甚至可以創建嵌套對象。
let firstName = "Darren";
let lastName = "Ji";
let person = {firstName, lastName};
let teamName = "恆大";
let team = {person, teamName};
console.log(team);
結果:
{person:{firstName: 'Darren', lastName: 'Ji'}, teamName: '恆大'}
只讀變量
變量值通常可以改變:
let a = 100;
a = 200;
console.log(a);
ES6中多了一個修飾符const,把變量設置成只讀。
const val = 'hi';
val = 'yes';
console.log(val);
Sets
ES6使用Set類構造集合。
let s = new Set([10, 20, 30]);
s.add(40);
console.log(s);
s.delete(30);
console.log(s);
結果:
[10, 20, 30, 40]
[10, 20, 40]
Maps
ES6使用Map類處理鍵值對集合。
var map = new Map(); var myKey = {name: 'darren'}; map.set(myKey, 'my favorite book'); //是否包含某鍵 console.log(map.has(myKey)); //根據鍵獲取值 console.log(map.get(myKey)); //遍歷值 for(var item of map.values()){ console.log(item); }
結果:
true
my favorite book
my favorite book
Symbols
ES6是唯一、不可變的,使用Symbol類創建Symbol實例。
Symbol可以作為鍵。
let a = new Map(); { let key = Symbol(); a.set(key, 'book'); console.log(a.get(key)); }
Symbol還可以作為對象的字段。
let courseName = Symbol(); let course = { publisher: 'hd', [courseName]: 'lesson' }; console.log(course);
結果:
{publisher: 'hd', Symbol(): 'lesson'}
如果想遍歷Couse對象的字段,Symbol()是獲取不到的。使用這一特點可以隱藏某些信息。
let courseName = Symbol(); let course = { publisher: 'hd', [courseName]: 'lesson' }; console.log(course); var props = []; for(var c in course){ props.push(c); } console.log(props.length); console.log(props);
結果:
{publisher: 'hd', Symbol(): 'lesson'}
1
publisher
但可以通過以下方式獲取到Symbol以及對應的值。
console.log(Object.getOwnPropertySymbols(course)[0]);
let keySymbol = Object.getOwnPropertySymbols(course)[0];
console.log(course[keySymbol]);
WeakMaps
不能使用字符串作為鍵。鍵只能是對象、函數。
var w = new WeakMap(); var course = {name: 't', publisher:'hd'}; var company = {name: 'sup'}; w.set(course, {price:59}); w.set(company, 's'); console.log(w.has(course)); w.delete(course); w.clear(course); console.log(w.get(company));
Promises
fetch("http://services.odata.org/V4/Northwind/Northwind.svc/",{ method: 'get' }).then(function(response){ return response.json(); }).then(function(data){ console.log(data.value); }).catch(function(){ console.log('failed'); });
還可以這么寫:
var promise = new Promise(function(resolve, reject){ $.ajax("http://services.odata.org/V4/Northwind/Northwind.svc/",{ success: function(data){ resolve(data); }, error: function(){ reject("Error"); } }) }); promise.then(function(result){ console.log(result); }, function(err){ console.log)(err); }); //如果有多個promise //Promise.all([promise]).then(function(results){ //results[0] results[1] ... },function(){ }) //Promise.race([promise]); //Promise.reject(reason);
創建類
class Shape{ constructor(w,l){ this.w = w; this.l = l; } render(){ console.log("開始構建圖形...") } } class Circle extens Shape{ constructor(w, l, radius){ super(w, l); this.radius = radius; } static getpi(){ return 3014; } get area(){ return Circle.pi * this.radius*this.radius; } render(){ console.log("正在構建圓形..."); } } var obj = new Circle(0, 0, 20); obj.l = 40; obj.render();
Modules
Module中的函數除非使用export,否則對外不可用。使用import使用某個函數。
● 通過export方法導出函數
addition.js
function sum(a, b){ return a + b; } function sumThree(a, b, c){ return a + b + c; } export {sum, sumThree};
main.js
import {sum, sumThree} from 'addition' console.log(sum(2,3)); console.log(sumTrhee(2, 3, 4));
● 通過函數上的export方法導出
addition.js
export function sum(a, b){ return a + b; } export function sumThree(a, b, c){ return a + b + c; }
● 導入函數使用別名
main.js
mport {sum as addTwoNumbers, sumThree} from 'addition'; console.log(addTwoNumbers(2,3)); console.log(sumTrhee(2, 3, 4));
● 給導入的函數統一的命名空間。
import * as addition from 'addition'; import {sum as addTwoNumbers, sumThree} from 'addition'; console.log(addition.sum(2,3)); console.log(addition.sumTrhee(2, 3, 4));
內置函數
//字符串 conole.log('ha'.repeat(2)); console.log("world".includes("rl")); console.log("Skill".startsWith("Skill")); console.log("Hello".endsWith("lo")); //遍歷字符串 for(var ch of 'hello'){ console.log(ch); } //近似值檢查 Math.trunc(39.7); //39 Math.trunc(0.5);//0 Math.trunc(-0.3);//-0 //數值類型檢查 Number.isNan(45) Number.isFinite(); //Sign Math.sign(); //數值安全性檢查 Number.isSafeInteger(42); //過濾數組 var result = ["","",""].find(x => x == ""); console.log(result); //從某個源獲取數組 var result = Array.from(document.querySelectorAll('*')); console.log(result); //從Map從獲取數組 var m = new Map([[1,2],[2,4],[4,8]]); console.log(Array.from(m)); //從字符串中獲取數組 console.log(Array.from("hello")); //創建數組 var arr = Array.of(1, 2, 3); //其它數組方法 [0, 0, 0].fill(7, 1); [1, 2, 3].findIndex( x => x == 2); [1, 2, 3, 4, 5].copyWithin(3, 1); //對象屬性賦值 //{distance:40, duration:20, interval:10, start:0} var first = {start:0}; var second = {interval:10, duration:20}; var third = {distance: 40}; Object.assign(first, second, third); console.log(first);