这个是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张牌