閉包
函數(shù)對(duì)象可以通過(guò)作用域鏈相互關(guān)聯(lián),函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi)夜只,這種特性稱(chēng)之為“閉包”赔硫。
當(dāng)一個(gè)函數(shù)嵌套了另外一個(gè)函數(shù),外部函數(shù)將嵌套的函數(shù)對(duì)象作為返回值返回的時(shí)候盐肃,我們會(huì)發(fā)現(xiàn)函數(shù)定義時(shí)的作用域鏈(函數(shù)內(nèi)的變量)到函數(shù)執(zhí)行時(shí)依然有效(被調(diào)用)爪膊。
閉包典型應(yīng)用實(shí)例:簡(jiǎn)單計(jì)數(shù)器
需求: 簡(jiǎn)單計(jì)數(shù)器权悟。計(jì)數(shù)器對(duì)象counter,屬性add推盛、subtract峦阁、reset。調(diào)用add()耘成,計(jì)數(shù)器+1榔昔;調(diào)用substract(),計(jì)數(shù)器-1瘪菌;調(diào)用reset()撒会,計(jì)數(shù)器歸零
//實(shí)例代碼1
function counter(){
var result = 0 ;
return{
add: function(){ return result++; },
subtract: function(){ return result--; },
reset: function(){ return result=0; }
};
}
var counter1 = counter(), counter2 = counter();
counter1.add() \\ => 0
counter2.add() \\ => 0
counter1.add() \\ => 1
counter1.reset() \\ => 0
//以上感覺(jué)沒(méi)有問(wèn)題。
counter1.reset() \\0
counter1.subtract() \\0
counter1.add() \\-1
counter1.add() \\0
//以上輸出就很奇怪了师妙,為什么在第一次subtract是0诵肛,后調(diào)用add,結(jié)果為-1默穴?
實(shí)例代碼2
function counter(){
var result = 0;
var func ={};
func.add = function(){
result++;
return result;
};
func.subtract= function(){
result--;
return result;
};
func.reset= function(){
result=0;
return result;
};
return func;
}
//result是一個(gè)函數(shù)內(nèi)的局部變量怔檩,但是卻起到了全局變量的效果,并且不會(huì)相互影響蓄诽⊙ρ担可以減少代碼之前的相互干擾,減少耦合性仑氛。
var counter1 = counter(), counter2 = counter();
counter1.reset() \\0
counter1.subtract() \\-1
counter1.add() \\0
counter1.add() \\1
//輸出正常乙埃,^ . ^
繼承
以前學(xué)習(xí)java中有類(lèi)和實(shí)例的概念。在JavaScript中锯岖,不區(qū)分類(lèi)和實(shí)例的概念介袜,而是通過(guò)原型(prototype)來(lái)實(shí)現(xiàn)面向?qū)ο缶幊獭?br>
原型繼承:
比如,創(chuàng)建一個(gè)Array
對(duì)象
var arr = [ 1, 2, 3 ];
其原型鏈?zhǔn)牵?br>
arr ----> Array.prototype ----> Object.prototype ----> null
因此Array.prototype
定義了indexOf()
嚎莉、shift()
等方法,因此可以再Array
對(duì)象上直接調(diào)用這些方法沛豌。
實(shí)例:
//父類(lèi) 人趋箩,具有屬性 名字和介紹自己的方法。
function person(name){
this.name = name; //必須使用this進(jìn)行綁定
this.hello = function(){
alert("Hello, I'm "+this.name+".");
};
}
//小明對(duì)象加派,繼承人的屬性和方法叫确。
var xiaoming = new person("小明"); //必須有new關(guān)鍵詞,變成構(gòu)造函數(shù)
xiaoming.name;
xiaoming.hello();
父類(lèi)還可以寫(xiě)成這樣:
function person(objname){
this.name = objname || "Unnamed";
}
person.prototype.hello()= function(){
alert("Hello, I'm "+this.name+".");
}
在ES6以后芍锦,新的關(guān)鍵詞class
可以定義類(lèi)了竹勉。
class person{
constructor(name) { //包含了構(gòu)造函數(shù)constructor
this.name = name;
}
hello() { //沒(méi)有function關(guān)鍵詞
alert('Hello, ' + this.name + '!');
}
}
同時(shí)繼承更加的方便,可以直接采用extends
關(guān)鍵詞實(shí)現(xiàn)
class seniorPerson extends person{
constructor(name,sex){
super(name);
this.sex = sex;
}
mySex(){
alert('I am a'+this.sex+'.');
}
}
多態(tài)
在學(xué)習(xí)java的時(shí)候娄琉,多態(tài)實(shí)際上是重載(Reload)或者重寫(xiě)(Rewrite)次乓。
- 重載:多個(gè)方法吓歇,方法名相同,參數(shù)的個(gè)數(shù)或者參數(shù)的類(lèi)型不一樣票腰。
- 重寫(xiě):子類(lèi)重寫(xiě)父類(lèi)的方法城看。
在JavaScript中如果函數(shù)名相同,后面的會(huì)把前面的函數(shù)覆蓋掉杏慰,因此不存在重載测柠。