我试图写一个对象的快速示例,以及该对象的一些原型,我从代码中得到了一些意想不到的结果。我正在处理两个文件,index.js和cards.js 基本思想是实例化一个名为" deck"然后在该对象上调用一些方法。这是我的代码
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
[]
看起来我从卡片洗牌中得到了正确的结果,但当我回头看看" 卡"包含,我得到意想不到的结果,即使我设置了值。我很难理解为什么会这样。另外,以这种方式返回结果是不好的形式,还是我应该使用传统的" return"像我在getCards方法中的声明?
提前致谢。
答案 0 :(得分: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);
});
另外,这里有关于this
答案 1 :(得分:3)
其他人已经回答了您的实施的具体问题(可能在您的回调中使用this
的值)。我发现它只是简化实现的方式,更容易:
这里没有理由使用递归。一个简单的while循环就足够了。这使得实现更简单,更高效,并且更容易调试。
此处没有理由使用回调来通知完成情况。这里的所有代码都是同步的您可以只调用该函数,当它返回时,结果就完成了。回调对于进度通知或异步事件未来某个时间的通知非常有用。当所有代码都是同步的时,使用回调来传递结果只是编写代码的一种更复杂的方式,并不是必需或有用的。
以strict
模式进行编程。这可能会立即将您的编程错误标记为错误,因为this
会undefined
而this.cards
会抛出一个立即错误,而不仅仅是做错了而不是告诉你。
总是在前面使用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;
}