—————————————————————————————————————————————————
用來控制網(wǎng)頁前進(jìn)和后退,根據(jù)的是網(wǎng)頁歷史紀(jì)錄
history.back(); //后退
history.forward();//前進(jìn)
history.pushState(data:json,title:string,url:string);// 會(huì)存儲(chǔ)在url歷史中
history.replaceState(data:json,title:string,url:string);// 不會(huì)存儲(chǔ)。。。
data是你要存放的數(shù)據(jù),可以使用history.state獲取,title是標(biāo)題,為空則不改變,url是新url
用來控制頁面跳轉(zhuǎn)
location.replace("xx");//跳轉(zhuǎn)
location.href = 'xxxx';//同上
location.reload();//刷新頁面
直接使用元素的onclick屬性:
<button onclick="btnhandler(this)"> click me </button>
綁定一個(gè)事件:
getElementById("xx").onclick = function(e){ xxxxxxxx; }
事件監(jiān)聽:
document.getElementById("xxx").addEventListener('click',function(e){ xxxxxx; })
注意:事件名稱前不加on
區(qū)別:
使用內(nèi)聯(lián)onclick屬性似乎只能傳遞自身而不能傳遞事件對象
事件監(jiān)聽可以在一種事件上綁定多個(gè)方法
注意:
當(dāng)元素是動(dòng)態(tài)生成的時(shí)候,在元素生成前綁定的事件無效,如:
$('.btn').click(function (e){ ...... }); $('body’).append('<button class="btn">...</button>'); // 單擊事件不能綁定到新的元素上面
element.onclick() || element.onclick.call() ;
jquery方式:$(sel).click();
onchange當(dāng)表單的值改變時(shí)觸發(fā)(需鼠標(biāo)抬起,不是即時(shí)的)
oninput當(dāng)表單控件受到改變時(shí)觸發(fā)(即時(shí)的)
事件對象自動(dòng)傳遞給回調(diào)函數(shù) element.onclick = function(e){};// e就是事件對象
e的常見屬性:
e.target;//獲取觸發(fā)此事件的元素(不一定是綁定元素)
e.currentTarget//獲取觸發(fā)此事件的元素(一定是綁定元素)
e.offsetX ||e.offsetY ;//獲取鼠標(biāo)基于target元素內(nèi)部的偏移x和y
e.clientX ||e.clientY ;//獲取鼠標(biāo)基于瀏覽器視窗的偏移x和y
e.keyCode ||e.which;//返回鍵盤上的字符的代碼
事件回調(diào)中的this:指向事件的觸發(fā)元素
----如果事件處理函數(shù)的綁定在元素生成之前,則此元素不能綁定事件處理函數(shù),需重新設(shè)置
var a = document.getElementById("xxx").style.width;
document.getElementById("xxx").style.width = '500px'//注意加上單位
element.currentStyle.width || getComputedStyle( element,null).width ;
前者是ie專用,后者是w3c標(biāo)準(zhǔn),注意:用這種方法只能獲取不能設(shè)置
$(sel).css(styleName);// 注意數(shù)據(jù)類型以及單位
注:行內(nèi)樣式一定是起作用的樣式,所以用js設(shè)置元素樣式都是設(shè)置行內(nèi)樣式
// 使用變換(transform)不會(huì)改變上述屬性的值
// 它們受left,top,margin等css屬性的影響,但不一定等于它們
// 建議使用offsetHeight,因?yàn)槠渌嘏帕形恢脮r(shí)是會(huì)考慮邊框和滾動(dòng)條的
offsetParent// 用于定位的基元素(默認(rèn)為最近的設(shè)置過position的父元素)
window.onscroll = function(e){ // 頁面滾動(dòng)事件(一般加給window) // 頁面被卷起來的高度距離頂部或底部的距離 var juan = document.documentElement.scrollTop; // 獲取頁面被卷起來的高度,documentElement相當(dāng)于html標(biāo)簽 var total = document.documentElement.scrollHeight; // 獲取頁面總高度 var visul = window.innerHeight; // 獲取可見區(qū)的高度(即瀏覽器顯示出來的高度) var bot = total - juan - visul; // bot就是可見區(qū)下面的高度(這是我們需要的) ........ // 當(dāng)bot小于某值時(shí),加載新元素 }
注:document的類型是Document,document.documentElement才是常規(guī)的Element類型的DOM元素
注:onscroll事件觸發(fā)次數(shù)比較頻繁,可以考慮節(jié)流(一段時(shí)間內(nèi)只執(zhí)行一次)
需要給被拖動(dòng)元素和window同時(shí)添加mousemove事件,因?yàn)榧词雇蟿?dòng)時(shí)鼠標(biāo)在元素之外,也應(yīng)該能實(shí)現(xiàn)拖動(dòng)。
具體實(shí)現(xiàn):
1.鼠標(biāo)按下目標(biāo)元素時(shí),存儲(chǔ)clientX,clientY,以及被拖動(dòng)元素的引用
2.鼠標(biāo)移動(dòng)時(shí),設(shè)置被拖動(dòng)元素的left為當(dāng)前clientX - 預(yù)先存儲(chǔ)的clientX,clientY同理
3.釋放鼠標(biāo)時(shí),清除之前存儲(chǔ)的數(shù)據(jù)
就是先不設(shè)置src,而是將路徑放到其他屬性中(如data-src),等到圖片處于顯示區(qū)或接近顯示區(qū)時(shí),再設(shè)置src
HTML DOM事件在:http://www.runoob.com/jsref/dom-obj-event.html
oncontextmenu
實(shí)例:
window.keydown = function(e){ //鍵盤事件一般和窗口綁定 var ev = window.event || e; //獲得事件對象(IE和其他瀏覽器均可用) var word = String.fromCharCode(ev.keyCode); //將ascii碼轉(zhuǎn)換成字符 alert(word); }
事件 描述
目前,需要根據(jù)瀏覽器種類加前綴
當(dāng)元素位置重疊的時(shí)候,點(diǎn)擊重疊的位置,每個(gè)元素的事件會(huì)按照一定的順序觸發(fā)。
若只想讓第一個(gè)事件觸發(fā),則可在那個(gè)事件的方法體中加入以下代碼:
e.stopPropagation();//中斷此次事件的后續(xù)操作
若顯示層級位于表層的元素沒有事件而里層元素有綁定事件,那么事件不會(huì)觸發(fā),因?yàn)槭录鞑皇且粋€(gè)通路。這在給父元素加鼠標(biāo)事件時(shí)很常用
事件相互影響的問題:
例如:如按空格讓視頻暫停,在文本框中輸入空格也可能會(huì)讓視頻暫停,這是因?yàn)槭录芭莸缴霞?,只需要在文本框上的鍵盤事件上中斷事件流即可
例如,在一個(gè)ul中為要每個(gè)li設(shè)置點(diǎn)擊事件,只需給ul設(shè)置點(diǎn)擊事件即可,li的事件會(huì)冒泡至ul上,通過this|e.target獲取li的DOM對象
瀏覽器默認(rèn)事件:
如:點(diǎn)擊a標(biāo)簽后,瀏覽器會(huì)默認(rèn)跳轉(zhuǎn)到指定頁面;點(diǎn)擊鼠標(biāo)右鍵,會(huì)彈出上下文菜單等
建立onclick事件方法,加入var ev=window.event; ev.preventDefault();
阻止a標(biāo)簽的默認(rèn)事件:
<a href="javascript:void(0)">鏈接</a>
this在事件處理函數(shù)中指向事件源對象(觸發(fā)事件的元素對象)
當(dāng)元素被批量選中時(shí),this指針對這些元素的事件處理非常有用
使用e.target也能獲取事件源對象// e表示事件對象
e.currentTarget表示最原始的觸發(fā)這個(gè)事件的對象(根據(jù)冒泡機(jī)制,只要條件符合,子元素也會(huì)觸發(fā)父元素身上的事件)
事件的傳遞分成三個(gè)階段:
PHASE1.捕獲:事件從祖先元素開始(從window開始)向內(nèi)傳遞
PHASE2.目標(biāo):事件已經(jīng)到達(dá)目標(biāo)(最內(nèi)層的命中事件的元素)
PHASE3.冒泡:事件向外(祖先)冒泡至window
默認(rèn)的偵聽器是偵聽冒泡階段的事件。
以點(diǎn)擊事件為例,鼠標(biāo)點(diǎn)擊后,會(huì)從window對象開始,檢索其子對象的區(qū)域是否包含點(diǎn)擊點(diǎn),html,body...直到某個(gè)元素的所有子元素的區(qū)域都不包含該點(diǎn)但自身包含該點(diǎn),則此元素為目標(biāo)元素,接著,從目標(biāo)元素開始,依次執(zhí)行點(diǎn)擊事件回調(diào),直到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中時(shí)間日期是以對象的形式實(shí)現(xiàn)的
var time = new Date();//獲得客戶端當(dāng)前的時(shí)間,返回一堆字符串,還可以用時(shí)間戳構(gòu)造(注意:客戶端的時(shí)間可能是不準(zhǔn)確的)
var time = new Date(年,月,日,時(shí),分,秒);//創(chuàng)建一個(gè)具體的時(shí)間
方法:
parseInt(str);// 會(huì)提取字符串中的整數(shù)部分,遇到非整數(shù)會(huì)立即停止提取;適合去掉css中的單位
parseFloat(str)// 同上,可以提取小數(shù)
Number.toFixed(n)// 保留n位小數(shù),為0則只保留整數(shù)
Number.round()// 返回最接近的整數(shù)(相當(dāng)于四舍五入)
Number.floor()// 向小取整
(function (){ //代碼塊 }());
或者
(function (){ // 代碼塊 })();
可以在前面加上 ; 提升可靠性
—————————————————————————————————————————————————
兄弟:$(sel).siblings(sel);
父級:$(sel).parent(sel);// 只能抓上一級
前輩:$(sel).parents(sel);// 可能是多個(gè)
第一個(gè):$(sel).first();
第n個(gè):$(sel).eq(n);
孩子:$(sel).chlidren(sel);// 注意只能抓下一級
取序號:$(sel).index();
$(sel).each(function (i,e)){ // i是序號,e是元素,只有一個(gè)參數(shù)時(shí),表示序號 // 代碼 } $.each(obj,function (i,e)){ // i是序號,e是元素,只有一個(gè)參數(shù)時(shí),表示序號 // 代碼 }
注:js中數(shù)組API的回調(diào)函數(shù)通常是function(e,i){},即序號在后
關(guān)于表單元素:注意table標(biāo)簽內(nèi)會(huì)自動(dòng)加一個(gè)tbody標(biāo)簽,獲取<tr>元素:$('table tbody tr');
hide(time,callback) show(...) fadeIn(...) fadeOut(...)
toggle動(dòng)畫:toggle() toggleFade() toggleSlide() 指根據(jù)display來判斷做什么動(dòng)畫
animate(json,timer,[timeFunc,callback]);
obj:格式是{attrName:styleValue, ...},表示元素要達(dá)到的樣式
timer:int類型,表示動(dòng)畫的毫秒數(shù)
timeFunc:速度函數(shù),有ease,linear等
callback: 回調(diào)函數(shù)
html()// 獲取或設(shè)置innerHTML
text()// 獲取或設(shè)置innerTEXT,會(huì)自動(dòng)轉(zhuǎn)義
val();// 獲取或設(shè)置value(只能用于表單)
position();//獲取匹配元素相對父元素的偏移,返回的對象包含兩個(gè)整型屬性:top 和 left
height();
width();
返回?cái)?shù)字,單位為px
jquery對象不能使用DOM對象的屬性和方法,jquery是對dom對象的封裝,使用jquery的0號元素即可獲得原來的DOM對象
$(sel)[0].setEventListener(....);
定義一個(gè)在頁面加載完成后立即執(zhí)行的函數(shù):
$(function (){ // 函數(shù)體 });
—————————————————————————————————————————————————
指向主調(diào)對象,或者window,其值是在運(yùn)行時(shí)可知的
函數(shù)對象:即Function類型的對象
實(shí)例對象:new 函數(shù)名()后生成的對象
function Foo(){ this.func = function (){ // 這是為實(shí)例添加方法:var obj = new Foo(); obj.func() ... } function func(){ // 沒有為任何對象添加方法,該函數(shù)僅在foo內(nèi)部可用,這是錯(cuò)的:foo.func() (×) ... } } Foo.func = function (){ // 這是為函數(shù)添加方法:foo.func() ... }
·所有函數(shù)都有prototype對象
·prototype對象是一個(gè)Object類型的對象
·該object對象中有一個(gè)constructor對象,指向該函數(shù)對象
·可以為prototype對象設(shè)置屬性,這些屬性實(shí)際是給實(shí)例對象訪問的
示例:
var func = function (){ } var f = new func(); func.prototype.print = function (){ console.log("print..."); } f.print(); // 控制臺輸出print... console.log(func.prototype.constructor === func) // true
所有實(shí)例對象都有一個(gè)__proto__屬性,也是object類型的,該屬性和其函數(shù)原型(構(gòu)造函數(shù))的prototype屬性是一樣的,它們共享一份Object對象,即函數(shù)對象.prototype = 實(shí)例對象.__proto__,在上述例子中就是func.prototype === f.__proto__
使用對象屬性(或方法)時(shí),先測試對象本身有無此方法,若沒有,則在__proto__中查找,直到找到,或不存在。這種查找鏈就是原型鏈(原型鏈?zhǔn)褂玫氖莀_proto__而不是prototype)。
實(shí)例(接上例):
f.toString();
// func中無toString方法,其原型中也無,于是通過__proto__到Object的原型中找,在Object中找到了toString方法,。
·Function和Object是系統(tǒng)內(nèi)置的函數(shù)。
·所有函數(shù)對象都是Function類型的實(shí)例(通過new Function()得到)
·Object是內(nèi)置的函數(shù)對象,也是Function類型的實(shí)例對象
·Function也是函數(shù)對象,它也是Function類型的實(shí)例對象
由以上三點(diǎn)可知:
·所有的函數(shù)對象都有prototype和__proto__兩個(gè)屬性,有prototype是因?yàn)樗泻瘮?shù)都有prototype對象,有__proto__是因?yàn)樗荈unction類型的實(shí)例
·所有函數(shù)對象的__proto__都等于Function對象的prototype,因?yàn)樗泻瘮?shù)對象都是Function對象的實(shí)例
·Function對象的prototype和__proto__是相等的
·prototype和__proto__的類型是Object,而Object本身也有prototype和__proto__屬性,Object的__proto__屬性等于Function對象的prototype(前面說過),Object對象的prototype屬性中有很多內(nèi)置的方法:
Object對象的prototype屬性不是Object類型的,而且該屬性的__proto__屬性為null,它是原型鏈的終點(diǎn)。
恒成立(假設(shè)用戶定義了一個(gè)函數(shù)函數(shù),名為Func):
Func instanceof Function // 因?yàn)镕unc.__proto__ == Function.prototype Func instanceof Object // 因?yàn)镕unc.__proto__.__proto__ == Object.prototype Function instanceof Function // 因?yàn)镕unction.__proto__ == Function.prototype Object instanceof Function // 因?yàn)镺bject.__proto__ == Function.prototype Function instanceof Object // 因?yàn)镕unction.__proto__.__proto__ == Object.prototype Object instanceof Object // 因?yàn)镺bject.__proto__.__proto__ == Object.prototype
L instanceof R當(dāng)且僅當(dāng)
L.__proto__......__proto__ === R.prototype
至少有一個(gè)__proto__
函數(shù)(或全局代碼)執(zhí)行前,會(huì)初始化上下文,包括:
例:
function foo(){ console.log(c) // undefined var c = 1; }
注:如果沒有定義變量,就直接使用,會(huì)在作用域鏈上查找,而不是在自身作用域上創(chuàng)建。
例1(以下是全局代碼):
function foo(){ username = 'zhangshan'; }
會(huì)設(shè)置window.username為'zhangshan',與函數(shù)中的this是誰無任何關(guān)系
例2:
function foo(){ this.username = 'zhangshan'; }
直接調(diào)用foo()時(shí),效果同上(直接調(diào)用某個(gè)函數(shù)時(shí),調(diào)用者一定是windows)
js支持函數(shù)的嵌套定義,內(nèi)部的函數(shù)叫子函數(shù),外部的函數(shù)叫父函數(shù)。
當(dāng)子函數(shù)引用了父函數(shù)中的變量,就會(huì)在子函數(shù)中產(chǎn)生一個(gè)閉包,包含了被引用的變量。
來看這個(gè)例子:
function foo(){ var msg="hello"; return function(){ return msg + " world"; } } var a = foo(); console.log(a()); // a能否正確使用msg?
foo()執(zhí)行完后,變量msg應(yīng)該被釋放,但是子函數(shù)引用了msg,產(chǎn)生了閉包,所以msg的生命周期變長,不會(huì)被釋放,所以執(zhí)行a()可以正確輸出msg的值。
產(chǎn)生閉包需要同時(shí)滿足:
1.存在函數(shù)嵌套
2.子函數(shù)中使用了父函數(shù)的變量
3.調(diào)用父函數(shù)
js是單線程的。
定時(shí)器回調(diào),DOM事件回調(diào),Ajax回調(diào)都會(huì)放在回調(diào)隊(duì)列中,待程序順序執(zhí)行完畢時(shí),才會(huì)執(zhí)行。
注:并不是回調(diào)都是異步任務(wù),比如Promise()的參數(shù)function會(huì)同步執(zhí)行
Object.create(obj,[property])
//使用指定對象作為__proto__產(chǎn)生一個(gè)新對象。
Object.defineProperty(obj,propname,conf)
// 給obj定義屬性propname,conf為配置項(xiàng)。
// 該函數(shù)可以監(jiān)視某個(gè)對象的改變,這是很多MVVM框架實(shí)現(xiàn)數(shù)據(jù)綁定的原理
Object.assign(target,source);
// 復(fù)制source的所有屬性到target并返回
詳詢:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object
Function.property.call(obj,param);
Function.property.apply(obj,[params]);
Function.property.bind(obj,param);
//均是 給函數(shù)指定this,其中bind不會(huì)執(zhí)行,而是返回該函數(shù)。
使用某個(gè)構(gòu)造函數(shù)new一個(gè)對象A實(shí)際上就是設(shè)置對象A的__proto__為構(gòu)造函數(shù)的prototype,然后將this設(shè)置為A來執(zhí)行構(gòu)造函數(shù)。
手動(dòng)實(shí)現(xiàn)new的方式:
function NEW(f){ // f為構(gòu)造函數(shù) 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);
如果某個(gè)變量(或表達(dá)式的結(jié)果)的值為undefined,null,'',0,false,則為假值,非上述值則為真值
即js的假值有多種,但!假值都是true,同理真值有無數(shù)種,但!真值都是false
空對象{}和空數(shù)組[]為真值
js的與或運(yùn)算(&&,||)并不產(chǎn)生true或false,而是:
在處理或運(yùn)算時(shí),返回第一個(gè)為真的值,若全為假,則返回最后一個(gè)假值
在處理與運(yùn)算時(shí),返回第一個(gè)為假的值,若全為真,則返回最后一個(gè)真值
在處理非運(yùn)算時(shí),一定返回true或false
關(guān)于相等性的研究請參考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Equality_comparisons_and_sameness
例:
var obj = createSomething() || {};// 若createSomething()返回假值,則將obj初始化為{}
例(將雙等==改成全等===的結(jié)果也是一樣的):
[undefined] == [undefined] // false,實(shí)際上無論數(shù)組里面是什么,該表達(dá)式始終返回false undefined == false // false undefined || false // false !undefined == true // true undefined && false // undefined false && undefined // false undefined || null // null '11.000' == 11 // true
和var一樣,定義變量,區(qū)別是:
1.支持塊級作用域
2.不能變量提升
定義常量,不能修改
例1:
let {name,age} = {'zhangshan',15} // 創(chuàng)建name,age兩個(gè)對象并依次賦值 let {name,age} = obj // 創(chuàng)建name,age兩個(gè)變量,并按obj中的字段名賦值 let [a,b,c] = [1,2,3] // 創(chuàng)建a,b,c三個(gè)變量,按索引號賦值
例2:
function foo({name,age}){....} // 同第二個(gè),按字段名賦值 foo(obj)
使用``包含,并使用${name}標(biāo)記變量,自動(dòng)拼接。
var str = `我叫${obj.name},今年${obj.age}歲`;
let obj = { name, // 直接將外部作用于的name賦給它,下同 age, setName(name){ // 相當(dāng)于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}
function foo(...value); // value會(huì)變成參數(shù)數(shù)組 function foo(arg1,...value); // value會(huì)變成除arg外的參數(shù)數(shù)組
...expression // 如果...后接一個(gè)可迭代對象,則此語句的作用是將該對象的所有可迭代屬性變成當(dāng)前對象內(nèi)的屬性
例:
var obj = { ...func(); }
如果func()函數(shù)返回一個(gè)可迭代對象,則上述語句表示將func()返回的對象中的所有屬性變成obj的
function point(x = 0,y = 0){ };
let foo = (params)=>{
statment;
}
foo(123);
注:lambda表達(dá)式中的this為它所在作用域中的this,且不能用call()更改,而一般函數(shù)的this需要在運(yùn)行時(shí)確定.
當(dāng)只有一個(gè)參數(shù)和一行語句時(shí)可簡略:param => expression;
let bar = param1 =>param2 => { statment;}
表示外層的箭頭函數(shù)的返回值是一個(gè)函數(shù)對象,也就是內(nèi)層的箭頭函數(shù)
即執(zhí)行bar()會(huì)得到內(nèi)層的函數(shù)對象
for...of語句可以遍歷實(shí)現(xiàn)了Iterator接口的對象(可迭代對象)。
例:
let arr = [2,3,4,5,5,6]; for(let e of arr){ // using e; }
數(shù)組,偽數(shù)組(類數(shù)組),set,map實(shí)現(xiàn)了Iterator接口,Object沒有實(shí)現(xiàn)該接口,但可以手動(dòng)實(shí)現(xiàn)。
手動(dòng)實(shí)現(xiàn)Iterator的方式:需要實(shí)現(xiàn)next方法,該方法返回此格式的對象{value:dataType,done:boolean},value是元素的值,done表示是否是最后一個(gè)元素
let it = Symbol.iterator; Object.prototype[it] = function (){ let next = ()=>{ return {value:....,done:....} } return {next}; }
注:使用for...in也可以迭代Object對象,使用Object.keys(obj)可獲取對象的key數(shù)組
是一種異步操作的解決方案,假設(shè)op1()和op2()是異步操作(回調(diào)函數(shù)),op2()需要依賴op1()先執(zhí)行。則op1和op2不能順序執(zhí)行,op2應(yīng)該位于op1的函數(shù)體中,如下例:
setTimeout(function op1(){ // do something... setTimeout(function op2(){ // do something... },2000); },2000);
如果回調(diào)層數(shù)過多,則會(huì)給編程帶來很大麻煩。使用promise解決方法如下:
// 定時(shí)器1的業(yè)務(wù)代碼
function func1(){ console.log('func1 do something'); }
// 定時(shí)器2的業(yè)務(wù)代碼
function func2(){ console.log('func2 do something'); }
function timeoutTask(timeoutFunc,delay){ // 返回一個(gè)Promise對象,其初始化參數(shù)為一執(zhí)行體(函數(shù)),倆參數(shù)分別表示執(zhí)行成功和失敗 return new Promise((success,error)=>{ setTimeout(function (){ timeoutFunc(); success(); // 執(zhí)行成功 },delay); }) }
// then方法接收兩個(gè)執(zhí)行體,分別對應(yīng)上一步執(zhí)行成功和失敗的回調(diào),then方法可以鏈?zhǔn)秸{(diào)用
timeoutTask(func1,2000).then(()=>timeoutTask(func2,2000),null);
是最常用異步操作的解決方案, async是配合promise使用的。
await后可以跟一個(gè)promise對象,只有promise對象resolve了,此表達(dá)式才會(huì)向下執(zhí)行
實(shí)例:Ajax異步獲取用戶個(gè)人信息,和用戶的文件列表,而且獲取文件列表的前提是已獲取用戶信息。
(async function (){ // 使用async修飾函數(shù) let user = await getUser(123); // 只有await關(guān)鍵字后的Promise對象為resolve狀態(tài),才會(huì)向下執(zhí)行,await表達(dá)式會(huì)返回resolve()的參數(shù)(即promiseValue) let files = await getFiles(user); // use files data... })(); // 若不手動(dòng)返回promise對象,async函數(shù)會(huì)強(qiáng)制返回一個(gè)promise對象,原本的返回值會(huì)作為promiseValue
await只能用在async塊中。
定義類
class Foo{ static msg = "Foo class"; // 靜態(tài)屬性 static getMsg = () => msg; // 靜態(tài)方法 constructor(){ // 構(gòu)造函數(shù) this.name = 'foo'; } setName(name){ // 普通函數(shù) this.name = name } }
在類定義中的普通函數(shù)會(huì)自動(dòng)原型化,再也不用手動(dòng)操作原型了;靜態(tài)屬性相當(dāng)于直接在類對象(非實(shí)例對象)本身添加
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
class Bar extends Foo {
}
機(jī)制幾乎和Java一模一樣;
支持super();
淺復(fù)制:一層復(fù)制,復(fù)制單層元素的值
深復(fù)制:多層遞歸復(fù)制
注:只有進(jìn)行了成員復(fù)制才能算拷貝,一般的對象間賦值只是指針的傳遞,根本不算拷貝。
例:
let a = [1,{name:"zhangshan"}]; let b = a.concat(); // concat是淺復(fù)制 b[0] = 2; b[1].name:"lishi"; console.log(a); // [1, {name: "lishi"}]
注:concat是淺復(fù)制,分別復(fù)制每一個(gè)元素的值,對于值類型的元素,復(fù)制其值,對于對象,復(fù)制其地址。
深復(fù)制的實(shí)現(xiàn):
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也可實(shí)現(xiàn)深復(fù)制