简体   繁体   English

试图了解nodeJS和javascript对象

[英]Trying to understand nodeJS and javascript objects

I was trying to write a quick example of a an object, and some prototypes for that object, and I was getting some unexpected results out of the code. 我试图编写一个对象的快速示例,以及该对象的一些原型,并且从代码中得到了一些意外的结果。 I'm working with two files, index.js and cards.js The basic idea is to instantiate a new object called "deck" and then call some methods on that object. 我正在使用index.js和cards.js这两个文件。基本思想是实例化一个名为“ deck”的新对象,然后对该对象调用一些方法。 Here's my code 这是我的代码

cards.js 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 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);

The results I get from running this code is below 我从运行此代码得到的结果如下

$ 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
[]

It looks like I'm getting proper results from my card shuffle, but when I look back at what " cards " contains, I get unexpected results, even though I'm setting the value. 看起来我从卡洗牌中得到了正确的结果,但是当我回顾“ ”中包含的内容时,即使设置了值,我也会得到意想不到的结果。 I'm having some trouble understanding why this is. 我很难理解为什么会这样。 Also, is it poor form to return results in this way, or should I be using a traditional "return" statement like I have in the getCards method? 另外,以这种方式返回结果的形式是否较差,还是应该像在getCards方法中一样使用传统的“ return”语句?

Thanks in advance. 提前致谢。

When you're in the callback scope, this.cards is referring to (and creating) the cards property of the callback function. 在回调作用域中, this.cards引用(并创建)回调函数的cards属性。 It's not the same scope as this.cards initially, so when you turn around and try to log it, you're logging that array that you spliced everything out of. 它的范围与最初的this.cards ,因此当您转过身来尝试对其进行记录时,您正在记录的是将所有内容拼接在一起的阵列。

There's a few ways to make it work. 有几种方法可以使其工作。 You can either capture the this above, in something like var self = this and use that self variable in the callback. 您可以使用诸如var self = this类的内容捕获上面的this ,然后在回调中使用该self变量。 You can bind() the callback functions this to intended value. 您可以bind()的回调函数this于预期值。 Or, you can set input_cards = return_deck at the end in place of your callback by returning the return_deck, or however you see fit. 或者,您可以通过返回input_cards = return_deck在结尾处设置input_cards = return_deck return_deck,或者返回合适的值。 In this situation, the callback isn't exactly necessary, because nothing you're doing is asynchronous, and it'll flow the same way regardless. 在这种情况下,回调并不是完全必要的,因为您所做的一切都不是异步的,无论如何它都将以相同的方式流动。

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

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

Also, here's some good reading about this 此外,这里的一些良好的阅读关于this

Others have answered the specific problem with your implementation (probably with the value of this in your callback). 其他人与你的实现(可能与价值回答特定问题this在回调)。 What I found was that it was way, way easier to just simplify the implementation: 我发现这是简化方式的一种方式,一种方法更容易:

  1. There's no reason to use recursion here. 这里没有理由使用递归。 A simple while loop will suffice. 一个简单的while循环就足够了。 This makes the implementation simpler, more efficient and a whole lot easier to debug. 这使实现更简单,更高效,并且更容易调试。

  2. There's no reason to use a callback here to notify of completion. 没有理由在这里使用回调来通知完成。 All code here is synchronous. 这里的所有代码都是同步的。 You can just call the function and when it returns, the result is done. 您可以只调用该函数,并在返回时完成结果。 Callbacks are useful for progress notifications or for notifications some time in the future of an asynchronous event. 回调对于进度通知或异步事件将来的某个时间的通知很有用。 When all code is synchronous, using a callback to pass the result is just a more complicated way of writing the code and is not necessary or helpful. 当所有代码都是同步的时,使用回调传递结果只是编写代码的一种更复杂的方式,并且没有必要或没有帮助。

  3. Program in strict mode. strict模式编程。 This would have flagged your programming mistake as an error immediately because this would have been undefined and this.cards would have thrown an immediate error rather than just doing the wrong thing and not telling you that. 这将立即将您的编程错误标记为错误,因为this将是undefined并且this.cards会立即引发错误,而不仅仅是做错事而不告诉您。

  4. Always declared local variables using var in front of them to avoid creating accidential, implicit global variables which will cause you problems in either recursive or async code. 始终在变量前面使用var声明局部变量,以避免创建意外的,隐式的全局变量,这会在递归或异步代码中引起问题。

Here's a simpler implementation: 这是一个更简单的实现:

"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;
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM