基礎篇
—————————————————————————————————————————————————
history:
用來控制網頁前進和后退,根據的是網頁歷史紀錄
history.back(); //后退
history.forward(); //前進
無重繪更改URL:
history.pushState(data:json,title:string,url:string); // 會存盤在url歷史中
history.replaceState(data:json,title:string,url:string); // 不會存盤,,,
data是你要存放的資料,可以使用history.state獲取,title是標題,為空則不改變,url是新url
location:
用來控制頁面跳轉
location.replace("xx"); //跳轉
location.href = 'https://www.cnblogs.com/liedElxa/p/xxxx'; //同上
location.reload(); //重繪頁面
定時器:
- var id = setInterval(callback,ms); //每隔ms毫秒執行一次函式(回呼函式只寫函式名)
- var id = setTimeout(callback,ms); //在ms毫秒后執行一次函式
- clearInterval(timer); //清理掉setInterval定時器
- clearTimeout(timeout); //讓setTimeout定時器失效
- window.requestAnimationFrame(callBack); //專門為影片設定的定時器(效果比setInterval流暢,每秒執行60次,大部分瀏覽器中,每秒執行次數和顯示幕重繪率一致)
事件系結的方法:
直接使用元素的onclick屬性:
<button onclick="btnhandler(this)"> click me </button>
系結一個事件:
getElementById("xx").onclick = function(e){
xxxxxxxx;
}
事件監聽:
document.getElementById("xxx").addEventListener('click',function(e){
xxxxxx;
})
注意:事件名稱前不加on
區別:
使用行內onclick屬性似乎只能傳遞自身而不能傳遞事件物件
事件監聽可以在一種事件上系結多個方法
注意:
當元素是動態生成的時候,在元素生成前系結的事件無效,如:
$('.btn').click(function (e){ ...... });
$(‘body’).append('<button >...</button>'); // 單擊事件不能系結到新的元素上面
手動呼叫事件:
element.onclick() || element.onclick.call() ;
jquery方式:$(sel).click();
onchange 當表單的值改變時觸發(需滑鼠抬起,不是即時的)
oninput 當表單控制元件受到改變時觸發(即時的)
事件物件:
事件物件自動傳遞給回呼函式 element.onclick = function(e){}; // e就是事件物件
e的常見屬性:
e.target; //獲取觸發此事件的元素(不一定是系結元素)
e.currentTarget //獲取觸發此事件的元素(一定是系結元素)
e.offsetX ||e.offsetY ; //獲取滑鼠基于target元素內部的偏移x和y
e.clientX ||e.clientY ; //獲取滑鼠基于瀏覽器視窗的偏移x和y
e.keyCode ||e.which; //回傳鍵盤上的字符的代碼
事件回呼中的this:指向事件的觸發元素
----如果事件處理函式的系結在元素生成之前,則此元素不能系結事件處理函式,需重新設定
獲得和設定元素的行內樣式(只針對行內樣式):
var a = document.getElementById("xxx").style.width;
document.getElementById("xxx").style.width = '500px' //注意加上單位
獲得作用在元素身上的樣式:
原生方式:
element.currentStyle.width || getComputedStyle( element,null).width ;
前者是ie專用,后者是w3c標準,注意:用這種方法只能獲取不能設定
jquery 方式:
$(sel).css(styleName); // 注意資料型別以及單位
注:行內樣式一定是起作用的樣式,所以用js設定元素樣式都是設定行內樣式
js獲取元素位置及大小:
- element.offsetTop; // 獲取元素相對于定位父元素(left,top屬性基于的元素)的頂部的距離
- element.scrollTop // 元素的滾動距離(該元素需要有滾動條,如果沒有則為0)【可寫】
- element.clientTop // 不常用
// 使用變換(transform)不會改變上述屬性的值
// 它們受left,top,margin等css屬性的影響,但不一定等于它們
- element.offsetHeight // 元素的高度(包括邊框,滾動條),回傳無單位的number值
- element.clientHeight // 不包括邊框滾動條的高度,如果邊框無滾動條,則同上
- element.scrollHeight // 如果有滾動條,則獲取滾動內容的高度,沒有滾動條則同上【可寫】
// 建議使用offsetHeight,因為其他元素排列位置時是會考慮邊框和滾動條的
offsetParent // 用于定位的基元素(默認為最近的設定過position的父元素)
滾動動態加載內容:
window.onscroll = function(e){ // 頁面滾動事件(一般加給window) // 頁面被卷起來的高度距離頂部或底部的距離 var juan = document.documentElement.scrollTop; // 獲取頁面被卷起來的高度,documentElement相當于html標簽 var total = document.documentElement.scrollHeight; // 獲取頁面總高度 var visul = window.innerHeight; // 獲取可見區的高度(即瀏覽器顯示出來的高度) var bot = total - juan - visul; // bot就是可見區下面的高度(這是我們需要的) ........ // 當bot小于某值時,加載新元素 }
注:document的型別是Document,document.documentElement才是常規的Element型別的DOM元素
注:onscroll事件觸發次數比較頻繁,可以考慮節流(一段時間內只執行一次)
js實作拖動:
需要給被拖動元素和window同時添加mousemove事件,因為即使拖動時滑鼠在元素之外,也應該能實作拖動,
具體實作:
1.滑鼠按下目標元素時,存盤clientX,clientY,以及被拖動元素的參考
2.滑鼠移動時,設定被拖動元素的left為當前clientX - 預先存盤的clientX,clientY同理
3.釋放滑鼠時,清除之前存盤的資料
獲取body標簽對應的DOM :document.body
獲取html標簽對應的DOM :document.documentElement
圖片懶加載:
就是先不設定src,而是將路徑放到其他屬性中(如data-src),等到圖片處于顯示區或接近顯示區時,再設定src
HTML DOM事件在:http://www.runoob.com/jsref/dom-obj-event.html
右鍵點擊事件
oncontextmenu
表單系結事件的考慮:
- onkeydown // 按下按鍵時立即觸發,該事件一般系結在document/window上,因為即使被系結的表單沒有獲得焦點,該事件也會執行
- onkeypress // 按下按鍵時立即觸發,只有被系結的元素獲得焦點了,才會執行事件(適用于動態search)
- onchange // 表單值改變時執行,按下按鍵時不是立即觸發,而是等到輸入完畢時才會觸發(輸入完畢指的是按下回車或表單失去焦點)
- oninput // 表單值改變時立即觸發
實體:
window.keydown = function(e){ //鍵盤事件一般和視窗系結 var ev = window.event || e; //獲得事件物件(IE和其他瀏覽器均可用) var word = String.fromCharCode(ev.keyCode); //將ascii碼轉換成字符 alert(word); }
影片事件:
事件 描述
- animationend 該事件在 CSS 影片結束播放時觸發
- animationiteration 該事件在 CSS 影片重復播放時觸發
- animationstart 該事件在 CSS 影片開始播放時觸發
- transitionend 該事件在 CSS 完成過渡后觸發,
目前,需要根據瀏覽器種類加前綴
事件流:
當元素位置重疊的時候,點擊重疊的位置,每個元素的事件會按照一定的順序觸發,
若只想讓第一個事件觸發,則可在那個事件的方法體中加入以下代碼:
e.stopPropagation(); //中斷此次事件的后續操作
若顯示層級位于表層的元素沒有事件而里層元素有系結事件,那么事件不會觸發,因為事件流不是一個通路,這在給父元素加滑鼠事件時很常用
事件相互影響的問題:
例如:如按空格讓視頻暫停,在文本框中輸入空格也可能會讓視頻暫停,這是因為事件冒泡到上級,只需要在文本框上的鍵盤事件上中斷事件流即可
事件委托:
例如,在一個ul中為要每個li設定點擊事件,只需給ul設定點擊事件即可,li的事件會冒泡至ul上,通過this|e.target獲取li的DOM物件
瀏覽器默認事件:
如:點擊a標簽后,瀏覽器會默認跳轉到指定頁面;點擊滑鼠右鍵,會彈出背景關系選單等
阻止默認事件:
建立onclick事件方法,加入var ev=window.event; ev.preventDefault();
阻止a標簽的默認事件:
<a href="javascript:void(0)">鏈接</a>
在事件處理函式中this的用法:
this在事件處理函式中指向事件源物件(觸發事件的元素物件)
當元素被批量選中時,this指標對這些元素的事件處理非常有用
使用e.target也能獲取事件源物件 // e表示事件物件
e.currentTarget表示最原始的觸發這個事件的物件(根據冒泡機制,只要條件符合,子元素也會觸發父元素身上的事件)
深入理解事件機制:
事件的傳遞分成三個階段:
PHASE1.捕獲:事件從祖先元素開始(從window開始)向內傳遞
PHASE2.目標:事件已經到達目標(最內層的命中事件的元素)
PHASE3.冒泡:事件向外(祖先)冒泡至window
默認的偵聽器是偵聽冒泡階段的事件,
以點擊事件為例,滑鼠點擊后,會從window物件開始,檢索其子物件的區域是否包含點擊點,html,body...直到某個元素的所有子元素的區域都不包含該點但自身包含該點,則此元素為目標元素,接著,從目標元素開始,依次執行點擊事件回呼,直到window物件,
ClickHandler(window,new MouseEvent(x,y)); bool ClickHandler(DOM * dom, MouseEvent * e){ List<DOM*> children = dom->children; bool hit = false; for(int i=0;i<children.length();i++){ hit = ClickHandler(children[i],e) ; if(hit){ e->phase = 3; e->currentTarget = children[i]; dom->eventListener('click').call(e); return true; } } if(dom.area.include(e->x,e->y)){ e->target = e->currentTarget = dom; e->phase = 2; dom->eventListener('click').call(e); return true; } else { return false; } }
日期物件:
js中時間日期是以物件的形式實作的
var time = new Date(); //獲得客戶端當前的時間,回傳一堆字串,還可以用時間戳構造(注意:客戶端的時間可能是不準確的)
var time = new Date(年,月,日,時,分,秒); //創建一個具體的時間
方法:
- getTime(); //獲得從1970年1月1日到物件時間的毫秒數(時間戳)
- get年月日時分秒的英文(); //獲得對應的時間橙分,如getDate()獲得日數
- Date.now() 回傳毫秒級時間戳
- toLocalDateTimeString() // 回傳本地化的日期時間字串(對于北京時間,會變成12小時制)
抽取字串中的數字:
parseInt(str); // 會提取字串中的整數部分,遇到非整數會立即停止提取;適合去掉css中的單位
parseFloat(str) // 同上,可以提取小數
Number.toFixed(n) // 保留n位小數,為0則只保留整數
Number.round() // 回傳最接近的整數(相當于四舍五入)
Number.floor() // 向小取整
定義一個匿名函式,自動執行:
(function (){ //代碼塊 }());
或者
(function (){ // 代碼塊 })();
可以在前面加上 ; 提升可靠性
常用DOM操作:
- appendChild(e) // 尾插
- insertBefore(e,ch) // 在子節點ch前插入e
- removeChild(e) // 洗掉子節點
- replaceChild(new,old) // 替換子節點
- ------------------------------------------------------
- parentNode // 父節點
- children // 子節點集合
- childNodes // 子節點集合
- firstChild // 第一個子節點
- lastChild // 最后一個子節點
- previousSibling // 前一個兄弟節點
- nextSibling // 下一個兄弟節點
- -------------------------------------------------------
- setAttribute(name,value) // 設定元素的屬性
- getAttribute(name) // 獲取屬性
- hasAttribute(name) // 屬性是否存在
- -------------------------------------------------------
- dataset // 獲取以data-開頭的屬性(回傳物件,只讀)
- classList // 獲取類名(類陣列物件,只讀)
jquery篇
—————————————————————————————————————————————————
獲取元素:
兄弟:$(sel).siblings(sel);
父級:$(sel).parent(sel); // 只能抓上一級
前輩:$(sel).parents(sel); // 可能是多個
第一個:$(sel).first();
第n個:$(sel).eq(n);
孩子:$(sel).chlidren(sel); // 注意只能抓下一級
取序號:$(sel).index();
迭代器:
$(sel).each(function (i,e)){ // i是序號,e是元素,只有一個引數時,表示序號 // 代碼 } $.each(obj,function (i,e)){ // i是序號,e是元素,只有一個引數時,表示序號 // 代碼 }
注:js中陣列API的回呼函式通常是function(e,i){},即序號在后
DOM節點操作:
- append('xxxx'); // 在節點文本后添加內容,回傳原來的jQuery物件,而不是添加的
- appendTo(jQuery) // 將元素節點添加至指定jQuery物件的尾部
- prepend('xxxx'); // 在節點文本前添加內容,回傳原來的jQuery物件,而不是添加的
- before('xxxx'); // 在節點之前添加內容(一般是新節點)
- after('xxxx'); // 在節點之后添加內容(一般是新節點)
關于表單元素:注意table標簽內會自動加一個tbody標簽,獲取<tr>元素:$('table tbody tr');
jquery影片:
hide(time,callback) show(...) fadeIn(...) fadeOut(...)
toggle影片:toggle() toggleFade() toggleSlide() 指根據display來判斷做什么影片
animate(json,timer,[timeFunc,callback]);
obj:格式是{attrName:styleValue, ...},表示元素要達到的樣式
timer:int型別,表示影片的毫秒數
timeFunc:速度函式,有ease,linear等
callback: 回呼函式
獲取內容:
html() // 獲取或設定innerHTML
text() // 獲取或設定innerTEXT,會自動轉義
val(); // 獲取或設定value(只能用于表單)
獲取寬高和位置:
position(); //獲取匹配元素相對父元素的偏移,回傳的物件包含兩個整型屬性:top 和 left
height();
width();
回傳數字,單位為px
jquery物件轉化為DOM元素物件:
jquery物件不能使用DOM物件的屬性和方法,jquery是對dom物件的封裝,使用jquery的0號元素即可獲得原來的DOM物件
$(sel)[0].setEventListener(....);
定義一個在頁面加載完成后立即執行的函式:
$(function (){ // 函式體 });
高級篇
—————————————————————————————————————————————————
函式中的this:
指向主調物件,或者window,其值是在運行時可知的
函式物件和實體物件:
函式物件:即Function型別的物件
實體物件:new 函式名()后生成的物件
為函式物件添加方法:
function Foo(){ this.func = function (){ // 這是為實體添加方法:var obj = new Foo(); obj.func() ... } function func(){ // 沒有為任何物件添加方法,該函式僅在foo內部可用,這是錯的:foo.func() (×) ... } } Foo.func = function (){ // 這是為函式添加方法:foo.func() ... }
js原型:
·所有函式都有prototype物件
·prototype物件是一個Object型別的物件
·該object物件中有一個constructor物件,指向該函式物件
·可以為prototype物件設定屬性,這些屬性實際是給實體物件訪問的
示例:
var func = function (){ } var f = new func(); func.prototype.print = function (){ console.log("print..."); } f.print(); // 控制臺輸出print... console.log(func.prototype.constructor === func) // true
所有實體物件都有一個__proto__屬性,也是object型別的,該屬性和其函式原型(建構式)的prototype屬性是一樣的,它們共享一份Object物件,即函式物件.prototype = 實體物件.__proto__,在上述例子中就是func.prototype === f.__proto__
使用物件屬性(或方法)時,先測驗物件本身有無此方法,若沒有,則在__proto__中查找,直到找到,或不存在,這種查找鏈就是原型鏈(原型鏈使用的是__proto__而不是prototype),
實體(接上例):
f.toString();
// func中無toString方法,其原型中也無,于是通過__proto__到Object的原型中找,在Object中找到了toString方法,,
Function和Object的原型:
·Function和Object是系統內置的函式,
·所有函式物件都是Function型別的實體(通過new Function()得到)
·Object是內置的函式物件,也是Function型別的實體物件
·Function也是函式物件,它也是Function型別的實體物件
由以上三點可知:
·所有的函式物件都有prototype和__proto__兩個屬性,有prototype是因為所有函式都有prototype物件,有__proto__是因為它是Function型別的實體
·所有函式物件的__proto__都等于Function物件的prototype,因為所有函式物件都是Function物件的實體
·Function物件的prototype和__proto__是相等的
·prototype和__proto__的型別是Object,而Object本身也有prototype和__proto__屬性,Object的__proto__屬性等于Function物件的prototype(前面說過),Object物件的prototype屬性中有很多內置的方法:
- constructor: Object()
- hasOwnProperty: hasOwnProperty()
- isPrototypeOf: isPrototypeOf()
- toString: toString()
- valueOf: valueOf()
Object物件的prototype屬性不是Object型別的,而且該屬性的__proto__屬性為null,它是原型鏈的終點,
恒成立(假設用戶定義了一個函數函式,名為Func):
Func instanceof Function // 因為Func.__proto__ == Function.prototype Func instanceof Object // 因為Func.__proto__.__proto__ == Object.prototype Function instanceof Function // 因為Function.__proto__ == Function.prototype Object instanceof Function // 因為Object.__proto__ == Function.prototype Function instanceof Object // 因為Function.__proto__.__proto__ == Object.prototype Object instanceof Object // 因為Object.__proto__.__proto__ == Object.prototype
instanceof探幽:
L instanceof R當且僅當
L.__proto__......__proto__ === R.prototype
至少有一個__proto__
函式執行背景關系:
函式(或全域代碼)執行前,會初始化背景關系,包括:
- 確定this
- 變數提升:var定義的變數會在同級代碼執行前先初始化為undefined
- 函式提升:函式定義會在同級代碼執行前先初始化
- 變數提升先于函式提升
例:
function foo(){ console.log(c) // undefined var c = 1; }
注:如果沒有定義變數,就直接使用,會在作用域鏈上查找,而不是在自身作用域上創建,
例1(以下是全域代碼):
function foo(){ username = 'zhangshan'; }
會設定window.username為'zhangshan',與函式中的this是誰無任何關系
例2:
function foo(){ this.username = 'zhangshan'; }
直接呼叫foo()時,效果同上(直接呼叫某個函式時,呼叫者一定是windows)
閉包:
js支持函式的嵌套定義,內部的函式叫子函式,外部的函式叫父函式,
當子函式參考了父函式中的變數,就會在子函式中產生一個閉包,包含了被參考的變數,
來看這個例子:
function foo(){ var msg="hello"; return function(){ return msg + " world"; } } var a = foo(); console.log(a()); // a能否正確使用msg?
foo()執行完后,變數msg應該被釋放,但是子函式參考了msg,產生了閉包,所以msg的生命周期變長,不會被釋放,所以執行a()可以正確輸出msg的值,
產生閉包需要同時滿足:
1.存在函式嵌套
2.子函式中使用了父函式的變數
3.呼叫父函式
事件輪詢:
js是單執行緒的,
定時器回呼,DOM事件回呼,Ajax回呼都會放在回呼佇列中,待程式順序執行完畢時,才會執行,
注:并不是回呼都是異步任務,比如Promise()的引數function會同步執行
Object物件:
Object.create(obj,[property])
//使用指定物件作為__proto__產生一個新物件,
Object.defineProperty(obj,propname,conf)
// 給obj定義屬性propname,conf為配置項,
// 該函式可以監視某個物件的改變,這是很多MVVM框架實作資料系結的原理
Object.assign(target,source);
// 復制source的所有屬性到target并回傳
詳詢:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object
Function物件:
Function.property.call(obj,param);
Function.property.apply(obj,[params]);
Function.property.bind(obj,param);
//均是 給函式指定this,其中bind不會執行,而是回傳該函式,
new探幽:
使用某個建構式new一個物件A實際上就是設定物件A的__proto__為建構式的prototype,然后將this設定為A來執行建構式,
手動實作new的方式:
function NEW(f){ // f為建構式 var obj = Object.create(f.prototype); f.call(obj); return obj; }
函式物件賦值注意:
var $ = document.querySelector; $(...) // Illegal invocation
原因: document.querySelector()的this是document而$()的this是不確定的.
解決:var $ = document.querySelector.bind(document);
與或運算子、相等性:
如果某個變數(或運算式的結果)的值為undefined,null,'',0,false,則為假值,非上述值則為真值
即js的假值有多種,但!假值都是true,同理真值有無數種,但!真值都是false
空物件{}和空陣列[]為真值
js的與或運算(&&,||)并不產生true或false,而是:
在處理或運算時,回傳第一個為真的值,若全為假,則回傳最后一個假值
在處理與運算時,回傳第一個為假的值,若全為真,則回傳最后一個真值
在處理非運算時,一定回傳true或false
關于相等性的研究請參考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
例:
var obj = createSomething() || {}; // 若createSomething()回傳假值,則將obj初始化為{}
例(將雙等==改成全等===的結果也是一樣的):
[undefined] == [undefined] // false,實際上無論陣列里面是什么,該運算式始侄訓傳false undefined == false // false undefined || false // false !undefined == true // true undefined && false // undefined false && undefined // false undefined || null // null '11.000' == 11 // true
ES6:
let關鍵字:
和var一樣,定義變數,區別是:
1.支持塊級作用域
2.不能變數提升
const關鍵字:
定義常量,不能修改
解構賦值:(假定obj為 {name:'zhangshan',age:20})
例1:
let {name,age} = {'zhangshan',15} // 創建name,age兩個物件并依次賦值
let {name,age} = obj // 創建name,age兩個變數,并按obj中的欄位名賦值
let [a,b,c] = [1,2,3] // 創建a,b,c三個變數,按索引號賦值
例2:
function foo({name,age}){....} // 同第二個,按欄位名賦值 foo(obj)
字串模板:
使用``包含,并使用${name}標記變數,自動拼接,
var str = `我叫${obj.name},今年${obj.age}歲`;
物件內的屬性和方法可以簡略:
let obj = { name, // 直接將外部作用于的name賦給它,下同 age, setName(name){ // 相當于function setName(name){} this.name = name } }
陣列/物件の賦值(使用...):
let a1 = ['a','b','c']; let a2 = [...a1]; let a3 = [...a2,...a1]; let o1 = {a:123,b:456}; let o2 = {...o1}
可變引數(rest):
function foo(...value); // value會變成引數陣列 function foo(arg1,...value); // value會變成除arg外的引數陣列
...運算子:
...expression // 如果...后接一個可迭代物件,則此陳述句的作用是將該物件的所有可迭代屬性變成當前物件內的屬性
例:
var obj = { ...func(); }
如果func()函式回傳一個可迭代物件,則上述陳述句表示將func()回傳的物件中的所有屬性變成obj的
默認引數:
function point(x = 0,y = 0){ };
箭頭函式(lambda):
let foo = (params)=>{
statment;
}
foo(123);
注:lambda運算式中的this為它所在作用域中的this,且不能用call()更改,而一般函式的this需要在運行時確定.
當只有一個引數和一行陳述句時可簡略:param => expression;
雙箭頭:
let bar = param1 =>param2 => { statment;}
表示外層的箭頭函式的回傳值是一個函式物件,也就是內層的箭頭函式
即執行bar()會得到內層的函式物件
iterator和for...of:
for...of陳述句可以遍歷實作了Iterator介面的物件(可迭代物件),
例:
let arr = [2,3,4,5,5,6]; for(let e of arr){ // using e; }
陣列,偽陣列(類陣列),set,map實作了Iterator介面,Object沒有實作該介面,但可以手動實作,
手動實作Iterator的方式:需要實作next方法,該方法回傳此格式的物件{value:dataType,done:boolean},value是元素的值,done表示是否是最后一個元素
let it = Symbol.iterator; Object.prototype[it] = function (){ let next = ()=>{ return {value:....,done:....} } return {next}; }
注:使用for...in也可以迭代Object物件,使用Object.keys(obj)可獲取物件的key陣列
promise:
是一種異步操作的解決方案,假設op1()和op2()是異步操作(回呼函式),op2()需要依賴op1()先執行,則op1和op2不能順序執行,op2應該位于op1的函式體中,如下例:
setTimeout(function op1(){ // do something... setTimeout(function op2(){ // do something... },2000); },2000);
如果回呼層數過多,則會給編程帶來很大麻煩,使用promise解決方法如下:
// 定時器1的業務代碼
function func1(){ console.log('func1 do something'); }
// 定時器2的業務代碼
function func2(){ console.log('func2 do something'); }
function timeoutTask(timeoutFunc,delay){ // 回傳一個Promise物件,其初始化引數為一執行體(函式),倆引數分別表示執行成功和失敗 return new Promise((success,error)=>{ setTimeout(function (){ timeoutFunc(); success(); // 執行成功 },delay); }) }
// then方法接收兩個執行體,分別對應上一步執行成功和失敗的回呼,then方法可以鏈式呼叫
timeoutTask(func1,2000).then(()=>timeoutTask(func2,2000),null);
async和await關鍵字:
是最常用異步操作的解決方案, async是配合promise使用的,
await后可以跟一個promise物件,只有promise物件resolve了,此運算式才會向下執行
實體:Ajax異步獲取用戶個人資訊,和用戶的檔案串列,而且獲取檔案串列的前提是已獲取用戶資訊,
(async function (){ // 使用async修飾函式 let user = await getUser(123); // 只有await關鍵字后的Promise物件為resolve狀態,才會向下執行,await運算式會回傳resolve()的引數(即promiseValue) let files = await getFiles(user); // use files data... })(); // 若不手動回傳promise物件,async函式會強制回傳一個promise物件,原本的回傳值會作為promiseValue
await只能用在async塊中,
class關鍵字:
定義類
class Foo{ static msg = "Foo class"; // 靜態屬性 static getMsg = () => msg; // 靜態方法 constructor(){ // 建構式 this.name = 'foo'; } setName(name){ // 普通函式 this.name = name } }
在類定義中的普通函式會自動原型化,再也不用手動操作原型了;靜態屬性相當于直接在類物件(非實體物件)本身添加
const foo = new Foo(); foo.setName('bar'); // ok Foo.setName('bar'); // Foo.setName is not a function Foo.msg = 'abc class'; // ok foo.getMsg(); // foo.getMsg is not a function
extends繼承:
class Bar extends Foo {
}
機制幾乎和Java一模一樣;
支持super();
淺復制和深復制:
淺復制:一層復制,復制單層元素的值
深復制:多層遞回復制
注:只有進行了成員復制才能算拷貝,一般的物件間賦值只是指標的傳遞,根本不算拷貝,
例:
let a = [1,{name:"zhangshan"}];
let b = a.concat(); // concat是淺復制
b[0] = 2;
b[1].name:"lishi";
console.log(a); // [1, {name: "lishi"}]
注:concat是淺復制,分別復制每一個元素的值,對于值型別的元素,復制其值,對于物件,復制其地址,
深復制的實作:
function deepCopy(data){ let ret; if(data instanceof Array){ ret = []; } else if(data instanceof Object){ ret = {}; } else { return data; } for(let i in data){ // i為key或索引,如果是for...of,則i為值 ret[i] = deepCopy(data[i]); } return ret; }
使用JSON也可實作深復制
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/4036.html
標籤:JavaScript
下一篇:vue 首屏優化
