【问题标题】:Trying to understand nodeJS and javascript objects试图理解 nodeJS 和 javascript 对象
【发布时间】:2014-12-23 03:00:25
【问题描述】:

我试图编写一个对象的快速示例,以及该对象的一些原型,但我从代码中得到了一些意想不到的结果。我正在处理两个文件,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
[]

看起来我从洗牌中得到了正确的结果,但是当我回顾“cards”包含的内容时,我得到了意想不到的结果,即使我正在设置值。我很难理解为什么会这样。另外,以这种方式返回结果是不是很糟糕,或者我应该像在 getCards 方法中那样使用传统的“return”语句?

提前致谢。

【问题讨论】:

  • 请在局部变量声明前使用var,这样您就不会创建意外的隐式全局变量。当一个简单的 forwhile 循环可以正常工作时,为什么要使用递归也不清楚。

标签: javascript node.js class object


【解决方案1】:

其他人已经回答了您实现的具体问题(可能在您的回调中使用 this 的值)。我发现简化实现是一种非常简单的方式:

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

  2. 这里没有理由使用回调来通知完成。这里的所有代码都是同步的。您可以只调用该函数,当它返回时,结果就完成了。回调对于进度通知或异步事件未来某个时间的通知很有用。当所有代码都同步时,使用回调传递结果只是一种更复杂的代码编写方式,没有必要也没有帮助。

  3. strict 模式下编程。这会立即将您的编程错误标记为错误,因为 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 因为创建了如此出色的答案,我感到有删除自己的冲动;)关于第 4 点,我认为 deck = new cards(); 是故意全局的,因此 OP 可以在控制台中对其进行检查。顺便说一句,你为什么从shuffle 方法中return this?是否允许 jQuery 样式的链接?
  • @xec - 我的var 评论主要是关于shuffle_helper() 内部的index 变量。而且,是的,我return this 是为了方便链接。它会让你去做deck.shuffle().getCards()
  • @jfriend00 感谢您的精彩解释!关于递归,您可能是对的;它最终在你重写它的方式上变得更加简单。
【解决方案2】:

当您在回调范围内时,this.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 reading 关于this

【讨论】:

    猜你喜欢
    • 2013-10-25
    • 2021-09-20
    • 2015-12-14
    • 1970-01-01
    • 2011-10-20
    • 2017-01-20
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多