2014-10-27 71 views
1

我想写一个对象的快速示例,以及该对象的一些原型,并且我得到了一些意外的结果。我正在处理两个文件,index.js和cards.js 其基本思想是实例化一个名为“deck”的新对象,然后调用该对象上的某些方法。这里是我的代码试图理解nodeJS和javascript对象

cards.js

//constructor 
function cardsClass() { 
     this.cards = [ 
       { suit: 'heart', number: 1, name: 'ace' }, 
       { suit: 'heart', number: 10, name: 10 }, 
       { suit: 'heart', number: 11, name: 'jack' }, 
       { suit: 'heart', number: 12, name: 'queen' }, 
       { suit: 'heart', number: 13, name: 'king' } 
     ]; 
} 

//class method 
cardsClass.prototype.getCards = function() { 
     return this.cards; 
} 

cardsClass.shuffle_helper = function (input_cards, return_deck, callback) { 

     if (input_cards.length !=0) { 
       index = Math.floor(Math.random() * input_cards.length); 

       if (input_cards[index]) { 
         return_deck.push(input_cards[index]); 
         input_cards.splice(index, 1); 
       } 

       cardsClass.shuffle_helper(input_cards, return_deck, callback); 
     } 

     else { 
       callback(null, 'success'); 

     } 

} 

//class method 
cardsClass.prototype.shuffle = function (callback) { 
     //set up a temp deck... 
     var return_deck = []; 

     cardsClass.shuffle_helper(this.cards, return_deck, function (err, results) { 
       this.cards = return_deck; 

       callback(null, this.cards); 
     }); 
} 

module.exports = cardsClass; 

index.js

var cards = require('./cards.js'); 

deck = new cards(); 

console.log(deck.getCards()); 

deck.shuffle(function (err, results){ 

     console.log ('our results of a deck.shuffle'); 
     console.log (results); 

}); 

console.log ('and this is what our getCards function returns'); 
console.log(deck.getCards()); 

console.log ('looking at deck.cards'); 
console.log (deck.cards); 

结果我从运行此代码获得低于

$ node index.js 
[ { suit: 'heart', number: 1, name: 'ace' }, 
    { suit: 'heart', number: 10, name: 10 }, 
    { suit: 'heart', number: 11, name: 'jack' }, 
    { suit: 'heart', number: 12, name: 'queen' }, 
    { suit: 'heart', number: 13, name: 'king' } ] 
our results of a deck.shuffle 
[ { suit: 'heart', number: 1, name: 'ace' }, 
    { suit: 'heart', number: 11, name: 'jack' }, 
    { suit: 'heart', number: 13, name: 'king' }, 
    { suit: 'heart', number: 10, name: 10 }, 
    { suit: 'heart', number: 12, name: 'queen' } ] 
and this is what our getCards function returns 
[] 
looking at deck.cards 
[] 

它看起来就像我得到p roper是我的卡片随机播放结果,但是当我回头看看“卡片”包含的内容时,即使设置了该值,我也会得到意想不到的结果。我在理解这是为什么时遇到了一些麻烦。另外,以这种方式返回结果的可怜形式,还是应该使用像getCards方法中那样的传统“返回”语句?

在此先感谢。

+0

请使用中的局部变量声明这样你就不会创造偶然的,隐含的全局变量前面'var'。当一个简单的'for'或'while'循环可以正常工作时,你也不清楚为什么要使用递归。 – jfriend00 2014-10-27 20:18:35

回答

3

其他人与你的实现(可能与this在回调的值)回答特定问题。我发现的是,这样简单实现就简单多了:

  1. 没有理由在这里使用递归。一个简单的while循环就足够了。这使得实现更简单,更高效,并且更容易调试。

  2. 没有理由在这里使用回调来通知完成。这里的所有代码是同步的。你可以调用函数,当它返回时,结果就完成了。回调对于进度通知或异步事件未来一段时间内的通知很有用。当所有的代码都是同步的时候,使用回调来传递结果只是编写代码的一种更复杂的方式,并不是必需的或有用的。

  3. Program in strict mode。这可能会将您的编程错误立即标记为错误,因为this应该是undefinedthis.cards会立即引发错误,而不是仅仅做错了事情而不会告诉您。

  4. 在他们面前始终使用var声明局部变量,以避免创建隐含的全局变量,这会导致您在递归或异步代码中出现问题。

这里有一个简单的实现:

"use strict"; 

//constructor 
function cardsClass() { 
     this.cards = [ 
       { suit: 'heart', number: 1, name: 'ace' }, 
       { suit: 'heart', number: 10, name: 10 }, 
       { suit: 'heart', number: 11, name: 'jack' }, 
       { suit: 'heart', number: 12, name: 'queen' }, 
       { suit: 'heart', number: 13, name: 'king' } 
     ]; 
} 

//class method 
cardsClass.prototype.getCards = function() { 
     return this.cards; 
} 

//class method 
cardsClass.prototype.shuffle = function (callback) { 
    //set up a temp deck... 
    var shuffledCards = []; 
    while (this.cards.length) { 
     var index = Math.floor(Math.random() * this.cards.length); 
     shuffledCards.push(this.cards[index]); 
     this.cards.splice(index, 1); 
    } 
    this.cards = shuffledCards; 
    return this; 
} 

工作演示:http://jsfiddle.net/jfriend00/Lwv4cc3x/

+1

+ 1为创建这样一个优越的答案,我觉得自己删除自己的冲动;)关于第4点我假设'deck = new cards();'是故意全局的,所以OP可以在控制台中检查它。顺便说一句,为什么你从'shuffle'方法返回这个'?是否有允许jQuery风格的链接? – xec 2014-10-27 20:46:47

+2

@xec - 我的'var'注释主要是关于'shuffle_helper()'中的'index'变量。而且,是的,我为了方便链接返回这个。它会允许你去做'deck.shuffle()。getCards()'。 – jfriend00 2014-10-27 21:33:30

+0

@ jfriend00感谢您的出色解释!你可能是正确的递归;它最终会以你重写它的方式变得更加简单。 – 2014-10-27 22:33:19

3

当您处于回调范围时,this.cards指的是(并创建)回调函数的cards属性。它与开始时的this.cards不一样,所以当你转过身来尝试记录它时,你会记录下你将所有东西拼成一团的数组。

有几种方法可以使其工作。您可以捕获上面的this,如var self = this,并在回调中使用self变量。您可以将bind()的回调函数this设置为预期值。或者,您可以通过返回return_deck来设置input_cards = return_deck以代替回调,或者您认为合适。在这种情况下,回调并不是完全必要的,因为您所做的任何事情都是异步的,并且无论如何都会以相同的方式流动。

cardsClass.shuffle_helper(this.cards, return_deck, function (err, results) { 
     this.cards = return_deck; // Not the same "this" as above. 

     callback(null, this.cards); 
}); 

而且,这里的some good readingthis