這個是JavaScript權威指南里example 9-7 的例子,在這裏與大家交流一下
/**
* 此方法將返回一個新對象(繼承於傳來的參數)
* @param {} p
* @return {}
*/
function inherit(p) {
if(p == null) //其實這裏可以寫成if(p);if可以檢測出undefined,null,false,"",0,NaN
throwTypeError();
if(Object.create) { //這裏檢查當前ECMAScript 版本,如果有create方法了則直接返回新對象,否則就用下來的方法來創建新對象
returnObject.create(p);
}
vart = typeof p; //typeof 可以檢查出 右邊 參數的對象類型
if(t !== "object" && t !== "function")
throwTypeError();
functionf() {
}
f.prototype= p; //這個句話是繼承的關鍵,表名 f 繼承於 p
returnnew f();
}
function enumeration(namesToValues) {
/**
*這function書上是這樣解釋的
*This is the dummy constructor function that will be the return value.
*至於你懂不懂,反正我不懂,懂的你希望能留言一下,解釋一下,謝謝
*/
varenumeration = function() {
throw"Can't Instantiate Enumeration";
};
/**
* 這是對enumeration的擴展,我目前是這麼理解的,擴展了:增加了一個構造function和幾個方法
* 這裏的proto 是一個引用,指向enumeration
* @type
*/
varproto = enumeration.prototype = {
constructor: enumeration, //這裏的enumeration是不是指的是上面enumeration的引用呢?有什麼作用?
toString: function() {
returnthis.name;
},
valueOf: function() {
returnthis.value;
},
toJson: function() {
returnthis.name;
}
};
enumeration.values= []; //擴展,增加了一個values的數據對象
/**
* 這是一個遍歷方法,比如這裏namesToValues爲{Club : 1,Diamond : 2},那麼name的值分別爲“Club”與”Diamond“
*/
for(name in namesToValues) {
vare = inherit(proto); //產生新對象 ,都繼承於proto
e.name= name;
e.value= namesToValues[name]; //
根據name來取得namesToValues裏的name的值,如Map
enumeration[name]= e; //
在enumeration增加一個name的屬性(這就是動態語言的特點吧)
enumeration.values.push(e);//加到values裏去,保存起來
}
enumeration.foreach= function(f, c) {
for(var i = 0; i < this.values.length; i++) {
f.call(c,this.values[i]); //
每次調用c對象裏的f方法,並傳入enumeration.values裏的值
}
};
returnenumeration;
}
/**
* 這是一個撲克牌的例子
* @param {} suit 爲方塊、紅星之類的
* @param {} rank 就是指2、3、4....K、A
*/
function Card(suit, rank) {
this.suit= suit;
this.rank= rank;
}
//這裏算是執行程序的入口吧
Card.Suit = enumeration({
Club: 1,
Diamond: 2,
Heart: 3,
Spades: 4
});
//執行後應該是這樣;親,你能看懂嗎?
Card.Rank = enumeration({
Two: 2,
Three: 3,
Four: 4,
Five: 5,
Six: 6,
Seven: 7,
Eight: 8,
Nine: 9,
Ten: 10,
Jack: 11,
Queen: 12,
King: 13,
Ace: 14
});
Card.prototype.toString = function(){
returnthis.rank.toString() + " of " +this.suit.toString();
};
Card.prototype.compareTo = function(that){
if(this.rank< this.rank) return -1;
if(this.rand> this.rank) return 1;
return0;
};
Card.orderByRank = function(a, b){
returna.compareTo(b);
};
//排序法則,優先對比紅心、黑桃....
Card.orderBySuit = function(a, b){
if(a.suit< b.suit) return -1;
if(a.suit> b.suit) return 1;
if(a.rank< b.rank) return -1;
if(a.rank> b.rank) return 1;
return0;
};
/**
* 這是一個遍歷的方法
* cards裏就放着4 * 13 個對象
* 意思就是得到全部撲克牌,比如new Deck();就可以得到4 * 13個牌了
* 這應該就是Deck的構造函數吧
* 這裏的foreach是上面定義的,有兩個參數,可這裏都只傳一個參數,第二個參數則爲null,傳null會有什麼影響呢?求指導...
*/
function Deck(){
varcards = this.cards = [];
Card.Suit.foreach(function(s){//外層爲紅心、黑桃等4種牌
Card.Rank.foreach(function(r){//內層爲2、3、4、5....K、A
cards.push(newCard(s,r));
});
});
}
/**
* 這方法是用來打亂牌的(洗牌)
* 這裏的Math.random() * (i +1) 寫得不錯,0 < Math.random() < 1 那裏整個值的範圍爲 0 到 i 了,不懂的請在紙上寫寫看,你就容易明白了
* @return {}
*/
Deck.prototype.shuffle = function(){
vardeck = this.cards, len = deck.length;
for(vari = len -1; i > 0; i --){
varr = Math.floor(Math.random() * (i +1)),temp; //Math.floor()是去一法的,比如0.9則取0,5.5則取5;這與Math.ceil()相反
temp= deck[i],
deck[i]= deck[r],
deck[r]= temp;
}
returnthis; //return this 是爲了方法鏈,如deck.deal(13).sort(Card.orderBySuit),執行順序爲從左到右
};
/**
* 在這裏的意思是刪除第n個後的撲克牌
* @param {} n
* @return {}
*/
Deck.prototype.deal = function(n){
if(this.cards.length< n){
throw"Out of cards";
}
returnthis.cards.splice(this.cards.length - n, n); //splice(m,n)是從數組裏刪除數據,從第m個開始(包括m),刪除n個數據;
};
var deck = (new Deck()).shuffle(); //得到全部撲克牌後,洗牌
var iii = deck.deal(13);
var hand = deck.deal(13).sort(Card.orderBySuit);
for(var i = 0; i < hand.length; i ++){
console.log(hand[i].toString());
}
/**
* 刪除每13張後全部的撲克牌,意思只要13張牌,然後排序,這裏的Card.orderBySuit,我一開始我不懂, 後來我懂了,不懂的同鞋可以去看看js 裏的sort的用法
* arrayObject.sort(sortby) sortby可選。規定排序順序。必須是函數
* 若 a 小於 b,在排序後的數組中 a 應該出現在 b 之前,則返回一個小於 0 的值。
* 若 a 等於 b,則返回 0。
* 若 a 大於 b,則返回一個大於 0 的值。
*
* 後面的for是我自己加上去了,可以打印出手上是哪13張牌