Function.prototype.method =
function
(name, func) {
//在Function的原型上增長一個函數叫作「method」。該方法會在「類」的原型上增長指定函數名的函數。
if
(!
this
.prototype[name]) {
this
.prototype[name] = func;
}
};
Object.method(
'superior'
,
function
(name) {
//增長一個超級方法。該方法保存它從原型上繼承來方法。用來模擬面向對象中的super關鍵字。
var
that =
this
,
method = that[name];
return
function
( ) {
return
method.apply(that, arguments);
};
});
var
mammal =
function
(spec) {
//定義一個哺乳動物類型。
var
that = {};
that.get_name =
function
( ) {
//獲取動物名字。
return
spec.name;
};
that.says =
function
( ) {
//動物打招呼的方法。
return
spec.saying ||
''
;
};
return
that;
};
//var myMammal = mammal({name: 'Herb'});//建立一個哺乳動物的實例。
var
cat =
function
(spec) {
//定義一個「貓」的類型。
spec.saying = spec.saying ||
'meow'
;
//爲這個類型指定一個「叫聲」,這裏是「喵」
var
that = mammal(spec);
//建立一個哺乳動物實例。
that.purr =
function
(n) {
//爲這個哺乳動物建立一個貓的咕嚕咕嚕聲音的方法「purr」
var
i, s =
''
;
for
(i = 0; i < n; i += 1) {
if
(s) {
s +=
'-'
;
}
s +=
'r'
;
}
return
s;
};
that.get_name =
function
( ) {
//獲取「貓」的名字。貓的叫聲(meow) + 貓的名字 + 貓的叫聲(meow)
return
that.says( ) +
' '
+ spec.name +
' '
+ that.says( );
}
return
that;
};
var
myCat = cat({name:
'Henrietta'
});
//建立一隻貓的實例。名字叫Henrietta
var
coolcat =
function
(spec) {
//建立一個「酷貓」的類型
var
that = cat(spec),
//建立一隻普通貓。
super_get_name = that.superior(
'get_name'
);
//保存普通貓的「獲取名字」的方法。
that.get_name =
function
(n) {
//酷貓有本身的「獲取名字」的方法,「like」 + 普通貓的「獲取名字方法」 + 「baby」
return
'like '
+ super_get_name( ) +
' baby'
;
};
return
that;
};
var
myCoolCat = coolcat({name:
'Bix'
});
//建立一隻酷貓。
var
name = myCoolCat.get_name( );
//酷貓的名字是like meow Bix meow baby
// 'like meow Bix meow baby'
|
上面採用prototype(原型擴展)的方式來實現「類」的繼承,如,酷貓 > 繼承 > 貓 > 繼承 > 哺乳動物。javascript
而下面採用了另一種思路:使用工廠模式來建立對象,不是經過複用原型。而是拆分零部件。每一個部件都是可拆卸,可組裝的方式,來達到另外一種代碼複用的效果。java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
function
createCar(numberOfDoors){
//造車廠,指定門的數量,並製造一輛汽車。
var
numberOfWheels = 4;
//輪子的數量是4.
function
describe(){
//描述一下車輛。
return
"I have "
+ numberOfWheels +
" wheels and "
+ numberOfDoors +
" doors."
;
}
return
{
//返回製造完成的汽車。
describe: describe
};
}
function
createOdometer(){
//加工車載里程計。
var
mileage = 0;
function
increment(numberOfMiles){ mileage += numberOfMiles;}
//里程計跑表的方法
function
report(){
return
mileage; }
//報告當前的里程數
return
{
//返回製造完成的里程計
increment: increment,
report: report
}
}
function
createCarWithOdometer(numberOfDoors){
//製造帶有里程計的汽車
var
odometer = createOdometer();
//製造一個里程計
var
car = createCar(numberOfDoors);
//製造一輛車
car.drive =
function
(numberOfMiles){
//將里程計安裝到汽車上,當汽車行駛的過程當中,調用里程計的跑表方法。
odometer.increment(numberOfMiles);
}
car.mileage =
function
(){
//報告汽車的里程,經過已安裝的里程計的報告方法,獲取里程。
return
"car has driven "
+ odometer.report() +
" miles"
;
}
return
car;
//返回製造並組裝完畢的汽車。
}
var
twoFn=createCarWithOdometer(100);
//創造一輛帶有100個門的汽車(固然不可能。。Σ( ° △ °|||)︴)
console.log(twoFn);
|
上述兩種方式,體現了javascript的精妙之處。app
在面嚮對象語言中:dom
採用了類繼承的方式,實現代碼複用。函數
在javascript中,並無真正的類。而是用「function」來表明一種類型,學習
好比:this
1
|
function
Person(){};
|
咱們能夠認爲,Person就是所謂的javascript中的「類」的概念。咱們能夠這樣spa
1
2
3
|
var
p =
new
Person();
alert(p
instanceof
Person);
//結果是true,由於p就是Person類型的一個實例。
alert(p
instanceof
Object);
//結果也是true,由於全部實例終歸都是Object。
|
而每一個類型是若是擴展本身的新方法的呢?就是經過類型的prototype這個屬性。prototype
只有function纔有prototype屬性。code
好比:
1
2
3
4
5
6
|
function
Person(){}
Person.prototype.say =
function
(){alert(
'hello'
);};
//人這種類型有打招呼的方法
var
p1 =
new
Person();
var
p2 =
new
Person();
p1.say();
//hello
p2.say();
//hello
|
這樣,全部實例就均可以用打招呼的方法了。
當咱們建立一個新的類型「男人」。想要繼承Person的話。就像下面這樣:
1
2
3
4
5
6
7
8
9
10
11
|
function
Man(){}
var
proto = Man.prototype =
new
Person();
//男人也是人啊,男人的原型就是以一個普通人爲標準來參考的,因此咱們建立一我的類,賦值給男人,讓男人來學習,參考人的特性。
proto.fight =
function
(){
//男人比起人來,脾氣大,所以有個打架的方法。
alert(
'I\'ll kick your ass!!'
);
}
var
m =
new
Man();
m.say();
//hello
m.fight();
//I'll kick your ass.這就是傳說中的一句話說不上來就開打。。。
|
原型繼承的核心就是這樣的。
而另一種思路就是工廠模式。
小汽車廠
輪子廠
里程計廠
卡車廠
小汽車廠須要輪子和里程計,分別向「輪子廠」和「里程計廠」要來了兩個現成的產品,直接安裝好,就完成了一輛小汽車。
卡車長也是同樣的。因此這種方式也是一種很好的代碼結構。