为什么我不能在回调中重用变量名?

时间:2012-10-23 15:39:44

标签: javascript node.js scope

我正在尝试在以下函数中重用名为user的变量:

UserModel.prototype.authenticate = function (doc, callback) {

    // check to see if the username exists
    this.users.findOne({ username: doc.username }, function (err, user) {

        if (err || !user)
            return callback(new Error('username not found'));

        // hash the given password using salt from database
        crypto.pbkdf2(doc.password, user.salt, 1, 32, function (err, derivedKey) {

            if (err || user.password != derivedKey)
                return callback(new Error('password mismatch'));

            // explicitly define the user object
            var user = {

                _id: user._id,
                type: user.type,
                username: user.username,
                displayname: user.displayname

            };

            return callback(err, user);

        });

    });

};

我尝试重新定义user回调函数中的pbkdf2变量。这不像我期望的那样有效。我比较user.password != derivedKey的行会中断,因为user在运行时未定义。 user回调方法参数不应该findOne仍然是实例吗?如果我将两个user变量中的任何一个更改为其他变量,它就会起作用。

我可以重命名变量,但这仍然让我感到疑惑。

2 个答案:

答案 0 :(得分:5)

问题是,你在函数上下文中声明了一个名为user的变量:

var user = { };

这将覆盖/重叠由外部函数context声明为形式参数的user。在 if-statement 之后声明该变量没有帮助。由var函数声明声明的变量在分析时被提升,因此事实上,var user语句放在内部函数的顶部。

答案 1 :(得分:1)

答案是因为hoisting,即使您在其他表达式(users)中使用变量var usersuser.password != derivedKey)后声明它,它也会首先解析,保留原始users引用。 several docs上有hoisting,可能最好对它们采取高峰。