ES6 and JavaScript:
##ES6語法的特性
Js中的then函數和nodejs中的回調能夠保證函數的異步和跳過阻塞的部分進行下一步。
-
順序次序不一致但對取值沒有影響:
var{bar,foo}={foo:"aaa",bar:"boo"};
-
循環的相關的寫法:
for a in obj //非常方便的進行對象的遍歷 for a of array//適合於進行一般的遍歷 arr.forEach(()=>{});//速度接近原始方式進行的速度 //常用的MAP遍歷結構 for(let [key.value] of map)
-
es7中async / await,爲解決function, 事件發佈和監聽方式模糊了異步方法之間的流程
可以完全取代promise, generator的應用,但注意async只能夠在函數內部進行應用
- 基本上任何一個函數都可以成爲async,使用async則表明這個函數是一個異步函數
async function foo(){} const foo = async funtion(){} const foo = async()=>{}//es6的寫法
-
在調用 async定義的函數時,使用await,可以簡單的理解爲函數掛起後等待promis進行返回。
//async/await相關的代碼 const printData = async function (filepath) { let keyword = await readFile(filepath); let count = await queryDB(keyword); let data = await getData(res.length); console.log(data); });
-
generator//es6
function後面加*號函數則函數可以變爲generator;執行generator將會返回一個遍歷器對象,用於遍歷generator內部的狀態。
//生成器的定義generator const gen function*() { yield 1; return 3; } //迭代器的定義iterator,迭代器是生成器的實例化 let g =gen(); g.next(); //在異步任務處使用yield關鍵詞,此時generator會將程序執行權交給其他代碼,而在異步任務完成後,調用next方法來恢復yield下方代碼的執行。
yeild
關鍵字後面需要是function
,promise
,generator
,array
或object
。可以改寫文章一開始的例子:const co = reuqire('co'); const task = function* (filepath) { let keyword = yield readFile(filepath); let count = yield queryDB(keyword); let data = yield getData(res.length); console.log(data); }); co(task, './sample.txt');
-
Promise通過進行鏈接的方式進行改造:
readFile('./sample.txt').then(content => { let keyword = content.substring(0, 5); return queryDB(keyword); }).then(res => { return getData(res.length); }).then(data => { console.log(data); }).catch(err => { console.warn(err); }); //通過then連接的鏈式操作,使代碼更加簡潔
Promise的相關方法函數:
-
reduce的相關用法:
//例子,previousValue初始值0,currentValue初始的值爲index[currentValue],初始的值爲0,index的初始值也爲0,array一直不發生改變 //previousValue2次以上爲上一次執行的值 [0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){ return previousValue + currentValue; }, 10);
-
weakmap是map的弱引用對象,只是相比於map上面少了很多函數方法,set和weakset也是類似的關係。
-
//JS提供5種內置對象之一 //map的常用方法 clear()方法, 刪除所有的鍵/值對; delete(key), 刪除指定的鍵/值對; entries()返回一個迭代器, 迭代器按照對象的插入順序返回[key, value]; forEach(callback , context) 循環執行函數並把鍵/值對作爲參數; context爲執行函數的上下文this; get(key) 返回Map對象key相對應的value值; has(key) 返回布爾值, 其實就是返回Map對象是否有指定的key; keys() 返回一個迭代器,迭代器按照插入的順序返回每一個key元素; set(key, value) 給Map對象設置key/value 鍵/值對, 返回這個Map對象(相對於Javascript的Set,Set對象添加元素的方法叫做add,而Map對象添加元素的方法爲set; [@@iterator] 和entrieds()方法一樣, 返回一個迭代器, 迭代器按照對象的插入順序返回[key, value]; //weakmap的常用方法 delete(key) : 刪除指定的鍵/值對; get(key) :返回Map對象key相對應的value值; has(key) :返回布爾值, 其實就是返回Map對象是否有指定的key; set(key):給Map對象設置key/value 鍵/值對, 返回這個Map對象;
-
-
JavaScript的繼承(JavaScript語言特性決定了,類即函數,函數即類),ES6中出現class使得更加像一個類
-
JavaScript的語法中並沒有多繼承的存在
-
實現多繼承:通過class裏面引用多個function
-
-
Reflect的屬性:(都是對於Object,JSON裏面的方法進行修改)
Reflect.deleteProperty(queRes[i],'count');//刪除指定的json對象屬性: Reflect.apply(target, thisArg, args)// Reflect.construct(target, args)//等同於new target(...args) Reflect.get(target, name, receiver)//查找並返回target對象的name屬性 Reflect.set(target, name, value, receiver)//設置target對象的name屬性 Reflect.defineProperty(target, name, desc)//等同於Object.defineProperty,用來爲對象定義屬性 Reflect.has(target, name)//相當於name in target Reflect.ownKeys(target)//返回對象的所有屬性,等同Object.getOwnPropertyNames與Object.getOwnPropertySymbols之和 Reflect.isExtensible(target)//表明當前對象是否可擴展 Reflect.preventExtensions(target)//阻止該對象進行擴展 Reflect.getOwnPropertyDescriptor(target, name) //等同於Object.getOwnPropertyDescriptor,用於得到指定屬性的描述對象,將來會替代掉後者 Reflect.getPrototypeOf(target) //讀取對象的__proto__屬性,對應Object.getPrototypeOf(obj) Reflect.setPrototypeOf(target, prototype) //用於設置目標對象的原型(prototype),對應Object.setPrototypeOf(obj, newProto)方法
-
JSON是用於TCP,http,websoket的常用數據交互格式,但傳入的是JSON字符串
常用的JSON對象和字符串轉換方法:
-
JSON字符串轉換爲JSON對象
let obj = eval('(' + str + ')');//1st let obj = str.parseJSON();//2nd let obj = JSON.parse(str)//3rd
-
JSON對象轉換爲JSON字符串
let last=obj.toJSONString(); ;//1st let JSON.stringify(obj);//2nd
-
-
塊級作用域:{}將函數進行分開,函數作用域,js中的函數作用域在函數外也是可見的,變量的提升,node在相同命名的情況下會優先執行函數;
-
特殊對象 arguments,無需指出參數名字就可以訪問,類似的則是數組;Function在某些情況下也可以作爲對象,一般使用語句var add = new Function(obj1,obj2)。
-
合併兩個數組和數組擴展在原JS中用:arr.splice(start,num,value), 新的方法中 let arr=[origin1, insertvalue,origin];
14.在nodejs中使用import語法:1.使用命令:node --experimental-modules test.mjs,2.在nodejs中package.json裏面添加:type:json;https://nodejs.org/api/esm.html#esm_ecmascript_modules
JavaScript tips
##JavaScript組成部分:核心(ECMAScript),文檔對象模型DOM,瀏覽器對象模型BOM
字面量/變量/常量和數據類型
-
變量 let /常量 const,ES6之前:var/無聲明(全局變量),var和let最大的區別是let的迭代循環不會受閉包影響, js會將函數的變量名提升到普通變量名之前。
-
標識符號的命名:必須以字母,在JQuery中則代表自身。
-
三種基本數據類型( Number,String,Boolean ),兩種引用數據類型(Object,array),兩種特殊數據類型(undefined,null);
-
轉換數據類型:JavaScript能識別4種類型的數字字面量:十進制數、二進制數、八進制數和十六進制數
parseInt("string",進制)://強制轉化爲整形,不填默認爲10進制 parseFloat("string",進制)://強制轉化爲浮點型不填,默認爲10進制 Boolean(value)//把給定的值轉換成Boolean型; Number(value)//把給定的值轉換成數字(可以是整數或浮點數); String(value)//把給定的值轉換成字符串。
-
特殊字符:
\n 換行 \r 回車 \t 製表符 \' 單引號 \" 雙引號 ` 重音符(tab鍵上方的按鍵) \$ 美元符 \\ 反斜線 \uXXX 任意的Unicode碼 \xXX Latin1字符 其他常用字符 \0 NUL字符 \v 垂直製表符 \b 退格 \f 分頁
-
模板字符串:${ } ,如果緊跟 $ 的值被包裹在大括號中,那麼該值就會被注入到字符串中
const message = `The curren temperatrue is ${currentTemp} \u00b0C`;
對象- js5種內置對象之一
本質上對象是一個容器,對象的容器可以隨着時間推移而改變。
基本語法:let obj={key:value},key必須是字符串或者符號,值可以是任意類型
//for...in是枚舉對象屬性的傳統方式
const SYM =Symbol();
const o={a:1,b:2,c:3,{SYM}:4};
for(let prop in o)
{
if(!o.hasOwnProperty(prop))continue;
console.log('${prop}:${o{prop}}');
}
數組處理(Array) - js5種內置對象之一
數組是一種特殊類型的對象。
數組的內容天生具有自然排序特性。鍵是數字,並且是有序的。它具有強大的傳遞信息的能力。
數組特性:
-
數組長度不固定,可以隨時添加和刪除元素。
-
數組中元素的類型是多樣的,每個元素都可以是任意類型。
-
數組從下標0開始。
//獲取子數組
arr.slice(start);
arr,slice(start,end);
arr.slice(-end);
//從任意位置添加或刪除元素
arr.splice(alterPos,count,elem)
//數組內的分割和替換
arr.copyWithin(targetPos,start,end)
//用指定值填充數組
arr.fill(1)//用相應數值填充過來
arr.fill(elem,start,end)
//數組反轉和排序
arr.reverse()
arr.sort()
//map&&filter
arr.map(x=>x.name)//可以把json的map轉換爲數組
arr.filter(condition)
//reduce轉化數組,可以將一個數組歸納爲一個單獨的值
const sum = arr.reduce({a,x}=>a += x,0)//a表示初始值arr[0],x表示第一個元素的值,然後循環運算
//字符串連接
arr.join(elem)
數組內容操作
push;pop//返回新數組的長度
unshift;shift
concat//在數組末尾添加多個元素
slice
splice
copyWithin//剪切並替換數組元素
fill//填充數組
reverse
sort
數組搜索
indexOf(簡單的值),findIndex(複雜的值)//查找元素的下標
lastIndexOf(簡單值)//查找最後一個元素的下標
find//元素本身
some//數組中符合條件的元素
every//數組中所有元素都符合給定條件
數組轉化
map//轉化數組中的所有元素
filter//根據給定條件排除數組元素
reduce//把整個數組轉化成另一種數組類型
join//把元素轉化成字符串合併
日期和時間(Date)- js5種內置對象之一
//moment.js爲日期提供支持方法
const m = moment().add(10,'hours').subtract(3,"days").endof('month');
//日期格式化
moment().format('Y-M-D h:m:s')
fromNow()//從現在算起
m爲未來10個小時以後的時間點倒退3天后所在月份的月底
//創建當前日期
const now = new Date();
//創建指定日期從0開始,9-10月
const halloweenParty = new Date(2016,9,31,19,0);
//創建指定日期和時間,19:00am = 7:00pm
const halloweenParty = new Date(2016,9,31,19,0)
//一些方法檢索Date對象的組件
halloweenParty.getFullYear();
getMonth();getDate();getDay();getHours();getMinutes();getSeconds();getMillseconds();
//上述時間所對應的UTC時間
getUTCFullYear();getUTCMonth();getUTCDate();
正則表達式(RegExp)-js5種內置對象之一
//簡單郵件識別器
const email = /\b[a-z0-9._-]+@[a-z_-]+(?:\.[a-z]+)+\b/;
//US手機號碼識別器
const phone = /(:?\+1)?(:?\d3\s?|\d{3}[\s-]?)\d{3}[\s-]?\d{4}/;
//基本正則表達式
const re1 = /going/ //可以搜索going的表達式
const re2 =new RegExP('going')//使用對象構造器的等價形式
//一些常用的正則方法
startWith(),endWith(),includes(),indexOf()
match(),search(),input.replace().test()//從字符串開始
re.exec//從正則表達式開始
{n}//精確n次,匹配5位數字
{n,}//至少n次,匹配5位或者5位以上的數字
{n,m}//最少n次,最多m次 /\d{2,5}/
?//0或者1,等價於{0,1}/[a-z]\d?/i
*//0次或者多次,匹配跟隨了0個或多個數字的字母 /a-z\d*/i 匹配跟隨了0個或者多個數字的字母,表示重複
+//1次或者多次 /a-z\d+/i 匹配至少跟隨一個數字的字母
\s\S能匹配所有的空格和非空格
函數替換
//保留class,id和href的屬性,並刪除其他內容
function sanitizeATag//獲取標籤
const parts = aTag.match(/<a\s+(.*?)>(.*?)<\/a>/i);
//parts[1]是<a>標籤中的屬性,parts[2]是<a></a>之間的內容
const attributes = parts[1]
.split(/\s+/);//接下來將其分割成獨立的屬性
return '<a'+attributes
.filter(attr=>/^(?:class|id|href)[\s+]/i.test(attr)) //過濾掉class.id和href之外的屬性
.join('')//將它們用空格連接起來
+'>'//關閉<a>標籤
+parts[2]//添加內容
+'</a>'//添加閉合標籤
replace函數的接受順序//整個匹配的字符串(等價$&)>>匹配上的組,有多少組就會有多少參數,原始字符串中的匹配偏移量,原始字符串
描點
//只有兩種描點:^和$,類似於標記物之類的
//一般字符串匹配的是整個字符串的開始和末尾,即使字符串中有換行;
//如果把某個字符串當作多行字符串(以換行符分隔來處理,就需要用到m選項)
const input = "One line\nTwo lines\nTree lines\nFour"
const beginners = input.match(/^\w+/mg);//{"One","Two","Three","Four"}
const endings = input.match(/\w+$/mg)
向前查找
//向前查找(?=<subexpression>)
//否定向前查找(?!<subexpression>)
//重要場景:密碼驗證
動態構造正則
const userRegex= new RegExp('@(?:${user.join('|')})\\b','g');//第一個反斜杆是用來轉義第二個反斜槓
text.match(userRegex)
表達式和運算符
- 算術表達式的優先級:PEMDAS(括指乘除加減)Parentless括號 Exponents指數 Multiplication乘法 Division除法 Addition加法 subtraction減法
- typeof能夠打印運算符,instanceof原型鏈測試,判斷是否在其中,與in比較類似
作用域和嚴格模式
異步編程
-
JavaScript對異步編程的支持有三個不同的階段:回調階段,promise階段和生成器階段
-
異步編程的4個主要使用場景:用戶輸入,網絡請求(如Ajax請求),文件系統操作(讀/寫文件等)刻意的時間延遲(比如警告)
-
setTimeout,setInterval和clearInterval都定義在全局對象中(在瀏覽器中是Window,在node中是global)
-
錯誤優先回調
const fs = require('fs'); const fname ='may_or_may_not_exist.txt' fs.readFile(fname,function(err,data){ if(err)return console('error reading file ${fname}:${err.message}') console.log('${fname}contents:${data'} })
-
Promise
-
Promise只會返回兩種事情:被滿足(success)和被拒絕(failure)裏面分別使用resolve(滿足)和reject的回調
-
resolve和reject可以被多次調用,但只有一次會起作用,且並沒有終止函數執行,只是修改promise的狀態
-
事件:EvenEmitter
-
promise鏈:
function launch(){ return new Promise((resolve,reject)=>{ console.log("on") setTimeout(function(){ resolve("In orbit"); },2*1000) }) } const c = new Countdown(5) .on('tick',i=>console.log(i+'...')); c.go() .then(launch) .then(msg=>{ console.log(msg); }) .catch(err=>{ console.error("Houston, we have a problem....") }) //開發人員不應該編寫自己的生成器運行器,應該使用co或者koa
-
DOM和JQuery以及Node
-
文檔對象的基本模型
<html> <head> <title></title> <js></js> <style></style> </head> <body> <h1></h1> <div> <h1></h1> text node <p></p> text node </div> </body> </body> </html>
-
對話框 alert() prompt() confirm()顯示帶有一段消息以及確認按鈕的對話
頁面加載事件 onload onunload
定時器 setTimeout,clearTimeout 指定時間後執行,setInterval 指定時間後反覆執行 clearInternal
-
Dom操作:
-
父節點:parentNode;
-
兄弟節點:nextSibling, nextElementSibling, previousSibling, previousElementSbling;
-
子節點firstChild, firstElementChild, lastChild, lastElementChild,
-
所有子節點:ChildNotes 標準屬性, children 非標準屬性
改變Html的輸出流:document.write(),改變html的內容 document.getElementById("p1").innerHTML = "Hello 實驗樓"; 改變HTML的屬性:document90.getElementById(id).attribute = new value; Dom能夠改變HTML元素的格式 document.getElementById(id).style.property=new style; style爲html相應元素的屬性 #創建節點:createElement("p")創建元素節點,createAttriute()創建屬性節點,createTextNode()創建文本節點 #插入子節點:appendChild()方法向節點添加最後一個子節點,insertBefore在指定子節點插入新的子節點, #刪除節點:removeChild() #替換子節點:replaceChild() #設置節點的屬性:getAttribute(名稱)獲取,setAttribute(名稱,值)設置,removeAttribute(名稱)刪除
-
-
事件捕獲與事件冒泡:三件事情來影響其他處理器的調用
- 第一種最常見的,即已經見過的preventDefault,它可以取消地址;事件會繼續傳播,但是defaultPrevented會被置成true
- 第二種是調用stopPropagation,時間傳播到當前元素之後,將不會繼續傳播(所有綁定到當前元素上的處理器都會被調用,但綁定到其他元素上的處理器不會被調用)
- 最後一件事,調用stopImmediatePropagation會阻止所有還未調用的處理器被調用(即使這些處理器被綁定在當前的元素上)
-
在JQuery的事件監聽器中,直接在處理器中返回false與調用stopPropagation是等價的,這是Jquery的約定,但不能在DOM API中進行使用。
-
事件的種類
-
拖拽事件(Drag events):實現了拖放事件的接口,比如drag start,drag, dragend,drop。
-
焦點事件(Focus events):用戶與可編輯的元素交互時執行的一些操作。當用戶“進入一個字段”會觸發focus事件,用戶離開時會觸發blur事件,當用戶修改字段時則會觸發change事件。onclick,onblclick
-
表單事件(Form events):當用戶提交一個表單(由submit或者對應的地方敲擊回車),會觸發表單上的submit事件。onsubmit,onreset
-
輸入設備事件(Input device events):常見的觸摸事件有鼠標觸摸事件(mousedown,move,mouseup,mouseenter,mouseleave,mouseover,mousewheel)和鍵盤事件(keydown,keypress,keyup)
-
媒體事件(media events):用於追蹤用戶與html5中的視頻,音頻播放器的交互
-
進度事件(Progress events):通知瀏覽器加載網頁的速度,最常用的是load
-
觸摸事件(Touch events):觸摸事件爲可觸摸設備提供了高級支持
-
一系列實現的例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #list li { list-style-type: none; width: 100px; height: 50px; line-height: 50px; background-color: beige; text-align: center; float: left; } #list li.current { background-color: red; } #list li a { text-decoration: none; } </style> </head> <body> <div id="menu"> <ul id="list"> <li class="current"> <a href="javascript:void(0)">首頁</a> </li> <li> <a href="javascript:void(0)">HTML</a> </li> <li> <a href="javascript:void(0)">CSS</a> </li> <li> <a href="javascript:void(0)">JavaScript</a> </li> <li> <a href="javascript:void(0)">關於</a> </li> <li> <a href="javascript:void(0)">幫助</a> </li> </ul> </div> <script> //獲取所有的li標籤, var liObjs = document.getElementById("list").getElementsByTagName("li"); //循環遍歷,找到每個li中的a,註冊點擊事件 for(var i = 0; i < liObjs.length; i++) { //每個li中的a var aObj = liObjs[i].firstElementChild; aObj.onclick = function() { //把這個a所在的li的所有的兄弟元素的類樣式全部移除 for(var j = 0; j < liObjs.length; j++) { liObjs[j].removeAttribute("class"); } //當前點擊的a的父級元素li(點擊的這個a所在的父級元素li),設置背景顏色 this.parentNode.className = "current"; }; } </script> </body> </html>
-
-
JQuery提供的text和html方法分別等於對DOM元素的textContent和innerHTML屬性進行賦值
//jQuery的基本實例 //方法1 $(document).ready(function(){ // 開始寫 jQuery 代碼... }); //方法2 $(function(){ // 開始寫 jQuery 代碼... }); //一個簡單的例子 $('p') .after('<hr>') .append('<sup>*</sup>') .filter(':odd') .css('margin-left','20px')
-
Ajax:在相應元素定義觸發事件,能夠在文件中定義觸發的函數
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script> function loadXMLDoc() { var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執行代碼 xmlhttp=new XMLHttpRequest(); } else { // IE6, IE5 瀏覽器執行代碼 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("myDiv").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","/try/ajax/ajax_info.txt",true); xmlhttp.send(); } </script> </head> <body> <div id="myDiv"><h2>使用 AJAX 修改該文本內容</h2></div> <button type="button" onclick="loadXMLDoc()">修改內容</button> </body>
-
Node相關的操作
-
exports有快捷語法和moudle.exports兩種表達方式,實際情況下多用第二個方法
//方法1,exports導出的這個對象名字仍然叫function exports.function=function((err,a)={ return a; }) //方法2,app.js module.exports對象導出時可用文件名作爲對象app //index.get=function((err,a)={ //return a; //}) class index{ } module.exports = index;
-
核心模塊,文件模塊,npm模塊,自定義函數模塊
核心模塊//不需要用顯示聲明,可以進行直接使用 文件模塊//自己定義的模塊,需要用require(./)進行使用 npm模塊//通過npm導入,需要用require進行定義 自定義函數模塊 //const debug = require('debug')('main') 直接將文件所包含的函數
-
文件,進程,操作系統,流
//文件系統 fs.writeFile();fs.readFile();fs.writeFileSync();fs.readFileSync(); //進程 process //子進程的模塊對外主要是三個函數:exec,exeecFile和fork 並且有其自身的同步函數 //流 const ws = fs.createWriteStream('streaming.txt',{encoding:'utf-8'}); //操作系統os
-
web服務
const http = require('http') const server = http.createServer((req,res)={ console.log('${req.method} ${req.url}'); res.end('hi') }) const port = 8080 server.listen(port,()={ console.log('server started on port ${port}') })
-
[1].(美)鮑爾斯. JavaScript學習指南(第三版)[M].北京:人民郵電出版社
[2]. 《JavaScript基礎》實驗樓課程 https://www.shiyanlou.com/courses/1238