閉包
函數(shù)對象可以通過作用域鏈相互關(guān)聯(lián),函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),這種特性稱之為“閉包”。
當(dāng)一個函數(shù)嵌套了另外一個函數(shù),外部函數(shù)將嵌套的函數(shù)對象作為返回值返回的時候,我們會發(fā)現(xiàn)函數(shù)定義時的作用域鏈(函數(shù)內(nèi)的變量)到函數(shù)執(zhí)行時依然有效(被調(diào)用)。
閉包典型應(yīng)用實例:簡單計數(shù)器
需求: 簡單計數(shù)器。計數(shù)器對象counter,屬性add、subtract、reset。調(diào)用add(),計數(shù)器+1;調(diào)用substract(),計數(shù)器-1;調(diào)用reset(),計數(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
//以上感覺沒有問題。
counter1.reset() \\0
counter1.subtract() \\0
counter1.add() \\-1
counter1.add() \\0
//以上輸出就很奇怪了,為什么在第一次subtract是0,后調(diào)用add,結(jié)果為-1?
實例代碼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是一個函數(shù)內(nèi)的局部變量,但是卻起到了全局變量的效果,并且不會相互影響??梢詼p少代碼之前的相互干擾,減少耦合性。
var counter1 = counter(), counter2 = counter();
counter1.reset() \\0
counter1.subtract() \\-1
counter1.add() \\0
counter1.add() \\1
//輸出正常,^ . ^
繼承
以前學(xué)習(xí)java中有類和實例的概念。在JavaScript中,不區(qū)分類和實例的概念,而是通過原型(prototype)來實現(xiàn)面向?qū)ο缶幊獭?br>
原型繼承:
比如,創(chuàng)建一個Array對象
var arr = [ 1, 2, 3 ];
其原型鏈?zhǔn)牵?br>
arr ----> Array.prototype ----> Object.prototype ----> null
因此Array.prototype定義了indexOf()、shift()等方法,因此可以再Array對象上直接調(diào)用這些方法。
實例:
//父類 人,具有屬性 名字和介紹自己的方法。
function person(name){
this.name = name; //必須使用this進行綁定
this.hello = function(){
alert("Hello, I'm "+this.name+".");
};
}
//小明對象,繼承人的屬性和方法。
var xiaoming = new person("小明"); //必須有new關(guān)鍵詞,變成構(gòu)造函數(shù)
xiaoming.name;
xiaoming.hello();
父類還可以寫成這樣:
function person(objname){
this.name = objname || "Unnamed";
}
person.prototype.hello()= function(){
alert("Hello, I'm "+this.name+".");
}
在ES6以后,新的關(guān)鍵詞class可以定義類了。
class person{
constructor(name) { //包含了構(gòu)造函數(shù)constructor
this.name = name;
}
hello() { //沒有function關(guān)鍵詞
alert('Hello, ' + this.name + '!');
}
}
同時繼承更加的方便,可以直接采用extends關(guān)鍵詞實現(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的時候,多態(tài)實際上是重載(Reload)或者重寫(Rewrite)。
- 重載:多個方法,方法名相同,參數(shù)的個數(shù)或者參數(shù)的類型不一樣。
- 重寫:子類重寫父類的方法。
在JavaScript中如果函數(shù)名相同,后面的會把前面的函數(shù)覆蓋掉,因此不存在重載。