Node.js從4.0開始,支持ES6的大多數新特性,例如:classes、typed arrays、generators、Promises、Symbols、collections、arrowfunctions、block scoping、template strings等。 javascript
(1)原始類型(Primitive Type):
string、number、bollean、null、undefined,原始類型數據直接賦值便可。html
(2)引用類型(Reference Type):
包含ES原生對象、Node.js對象、用戶自定義對象三類;引用類型數據通常須要使用new關鍵字進行建立。 前端
ES6標準中,可使用"模板"方式定義字符串:java
var info=` 用戶名:tom 密碼:123456 `;
複製代碼
模板字符串中可使用${}拼接變量,並執行運算:編程
var price=3.5,count=3;
var info=` 單價:${price} 數裏:${count} 小計:${price*count} `
console.log(info);
複製代碼
(1)聲明常量數組
var empName1='tom';//局部變量
empName2='Mary';//全局變量
複製代碼
注意:省略var的全局變量在嚴格模式下是非法的閉包
(2)聲明常量—ES6新特性框架
const fs=require('fs');
複製代碼
ES6中,變量的做用域分爲三種:
(1)局部做用域:只能在當前函數內使用
(2)全局做用域:能夠在任意函數內使用—是全局對象的成員
(3)塊級做用域:只能在當前塊內使用—ES6新特性編程語言
"use strict";
for(let i=0;i<10;i++){
console.log(i)//正常執行
}
console.log(i)//執行錯誤
複製代碼
(1)算術運算 | + - * / % ++ -- |
---|---|
(2)比較運算 | > < >= <= == ==== != !== |
(3)邏輯運算 | && |
(4)位運算 | & |
(5)賦值運算 | += -= *= /= %= |
(6)三目運算 | ? : |
(7)特殊運算 | typeof (判斷變量類型) instanceof(判斷一個對象是否從屬於某種類型) viod(對任何值返回undefined) , . [ ](取下標運算符) => |
(1)循環結構函數
for | |
---|---|
for...in... | 經常使用於遍歷對象 |
for...of... | 只能遍歷數組,不能遍歷對象(ES6新特性) |
while | |
do...while |
(2)選擇結構
if...else... | |
---|---|
switch...case... |
(1) for...in循環能夠遍歷數組的下標或對象成員名
var arr=[90,80,70]
for(var i in arr){
console.log(i);//將輸出0 1 2
}
複製代碼
(2)ES6新增的for...of循環能夠遍歷數組的元素值
var arr=[90,80,70];
for(var v of arr){
console.log(v);//將輸出90 80 70
}
複製代碼
函數:就是一系列語句的集合,爲了實現某種能夠重複使用的特定功能。
(1)命名函數:指定了名稱的函數對象
function add(num1,num2){
return num1+num2;
}
add(10,20);
複製代碼
(2)匿名函數:未指定名稱的函數對象
function(num){
arguments.calle(num-1);//遞歸調用匿名函數
}
複製代碼
JS中,全局變量會變成全局對象的成員,形成全局對象的污染;不少JS工具和框架都在設計時,爲了不此問題,經常使用匿名函數的自調:
(function(g){
var ns="myNamespace";
})(global);
複製代碼
+function(g){
var ns="myNamespace";
}(global)
複製代碼
匿名函數在使用時必須使用function關鍵字,在大型的WEB應用中匿名函數會使用的不少不少,因此ES6中爲了簡化這種匿名函數的用法,引入了箭頭函數的概念。
ES6中,爲了簡化匿名函數的編寫,引入了監聽函數語法:
setInterval(()=>{
console.log('timer...');
},1000);
複製代碼
箭頭函數()是形參列表,function關鍵字被省略,小括號和大括號中間使用箭頭指示符鏈接;大括號中仍是普通函數同樣編寫函數體。從此在編寫Node.js程序中會常用箭頭函數,Node.js官方給出的例子也幾乎都是使用的箭頭函數。
fs.readFile('index.html',(err,data)=>{
if(err)throw err;
console.log(data);
});
複製代碼
箭頭函數與普通匿名函數的區別:
一、普通匿名函數中使用了this,this指當前函數對象;
二、在箭頭函數中this指與箭頭函數自己同一級的this;
三、在箭頭函數中使用arguments.callee不在指向當前匿名函數。
閉包(Closure),是ECMAScript中特有的現象。一個閉包,能夠看作一種特殊的對象,包含若干函數對象,以及這些函數對象執行時必須依賴的執行上下文對象。
function outer(){
var num=10;
function inner(){
console.log(num)
}
return inner;
}
var fn=outer();
fn();
複製代碼
有一個function,外部函數叫outer,outer有一個形參叫num=10,咱們知道num實在outer函數體內,那麼他的做用範圍也是僅限於outer函數內,離開outer那麼num也沒有做用了。在outer函數內又定義了一個內部函數叫inner,inner函數須要輸出num變量,因爲inner內部函數內並無定義,因此會使用outer內定義的局部變量num。outer函數自身並無調用inner,而是將inner內部函數return返回了。outer函數被調用,就會有一個返回值指向了inner函數,也就說fn指向了inner函數,inner函數被外部調用。inner函數不能直接被調用,由於inner函數執行必須依賴一個外部函數執行時,他建立的上下文對象所遺留的num變量。每一次調用outer函數,都返回了一個函數對象,以及這個函數對象運行所必須依賴的一個外部函數提供的上下文。(每調用一次outer函數都會產生一個閉包對象)
不管是前端JS仍是Node.js,閉包使用不當,都有可能引發看似奇怪的錯誤:
//假設前端項目有三個button元素
var list=document.querySelectAll("button");
for(var i=0;i<list.length,i++){
list[i].onclick=function(){
console.log(i);
}
}
//點擊每一個按鈕,會分別輸出什麼?
複製代碼
理想結果:三個按鈕,點擊第幾個按鈕就輸出數字對應的下標
實際結果:點擊每一個按鈕都會輸出數字3
緣由?:這段代碼中給這三個按鈕各自綁定了一個匿名的監聽函數,至關於這段代碼執行完成後給外界返回了三個函數對象,這三個函數運行都須要依賴於外部產生的執行上下文對象,他裏邊有且只有一個i(三個函數對象,外加一個執行上下文對象裏的i,這是一個典型的閉包)。循環結束變量i停留在3上,最終任何一個按鈕被點擊時,他們再去查找變量i,變量i已經被固定在3了,因此不會拿到0、一、2這種結果。
使用Node.js,也能夠產生相似前端中的閉包錯誤:
//目標:1s後,先輸出0、一、2
for(var i=0;i<3;i++){
setTimeout(()=>{
console.log(i)
},1000)
}
//實際的運行結果呢?
3
3
3
複製代碼
那麼咱們怎麼解決呢?
for (var i = 0; i < 3; i++) {
setTimeout(((num) => {
return () => {
console.log(num)
}
})(i), 1000);
}
複製代碼
ECMAScript中提供了多種建立對象的語法:
(1)對象直接量方式(這種對象不具備反覆使用性)
var e1={ename:'tom',work:function(){}}
複製代碼
(2)構造函數方式
function Emp(ename){
this.ename=ename;
this.work=function(){}
}
var e2=new Emp('tom');
複製代碼
這裏邊指定emp所須要的成員屬性和成員方法,咱們在須要emp類型對象時,能夠直接new一個emp對象。
(3)原型繼承方法
var parent=new Object();
var child=Object.create(parent);
複製代碼
先建立一個parent對象,再使用Object.creaet()方法建立一個parent對象的子對象。
(4)class方式—ES6新特性
ES6借鑑了其餘編程語言聲明對象的方式,正式啓用了class關鍵字,有了"類"的概念。
class:類,是一組類似對象的屬性和行爲的抽象集合。
instance:實例,是從屬於某個類的一個具體對象。
//class關鍵字必須用嚴格模式
"use strict"
//聲明一個類
class Emp{
//構造方法
constructor(ename){
this.ename=ename;
}
//實例方法
work(){
console.log(`ENAME:${this.ename}`);
}
}
//建立類的實例
var e3=new Emp('tom');
e3.work();
複製代碼
繼承,是面向對象編程的一個重要概念,使子對象能夠繼承父對象中聲明的成員,從而極大的提升代碼的複用性。
ES6以前的繼承都是經過對象的原型(prototype)來實現的:
var graphic={bgColor:'red',borderColor:'blank'}
var rect={width:500,height:300}
Object.setPrototypeOf(rect,graphic);//原型繼承
console.log(rect.width);
console.log(rect.hight);
console.log(rect.bgColor);//繼承來的成員
console.log(rect.borderColor);//繼承來的成員
複製代碼
ES6中的繼承經過使用class配合extentds關鍵字來實現。
//聲明父類
class Emp{
constructor(ename){
this.ename=ename;
}
work(){
return `ENAME:${this.ename}`;
}
}
//聲明子類
class Programmer extends Emp{
constructor(ename,skills){
//調用父類構造方法
super(ename);
this.skills=skills;
}
work(){
return super.work()+`SKILLS:${this.skills}`;
}
}
var p1=new Programmer('tom','js');
console.log(p1.work());
複製代碼
(1)ECMAScript預約義對象
String、Boolean、Number、Date、Array、Math、RegExp、function、Object、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、UriError等16個對象;
(2)Node.js核心模塊定義的對象
Bufefer、WriteStream、Socket、ChildProcess等數百個;
(3)等三方模塊定義的對象
(4)用戶自定義的對象注意:Node.js中不支持BOM和DOM對象,如:window、document等