如何编写OO Javascript来实现简单的类模式困惑

我确信之前已经问过这个问题,但是我完全被OO Javascript所困惑,所以我甚至不能认识到同样的问题。

我正在尝试编写将执行以下常见types模式的Javascript类:

var User=require('./models').User(); User.findUserById('1', function(err, user) {console.log(user)}); var newUser = new User(); // set the user's local credentials newUser.local.email = 'simon@infoqual.net'; newUser.local.password = newUser.generateHash('hello'); // save the user newUser.save(function(err) { if (err) throw err; console.log(newUser); //returns undefined for the attributes set above return newUser; }); 

目前,我的getter属性中没有一个属于我的内部保存function。 这是我正在写的全class的代码。

 exports.User = User; function User() { var user_uuid, local_email, local_password, user=this; function generateHash(password) { return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); } function validPassword(password, password_compare) { return bcrypt.compareSync(password, password_compare); } function findUserByEmail(email, callback) { conn.query("SELECT * FROM users WHERE local_email=$1 LIMIT 1", [email], function (error, result) { //var user = this.User; if (!error) { if (result.rowCount > 0) { local_email = result.rows[0].email; user_uuid = result.rows[0].user_uuid; //load rest of user obj callback(error, user_uuid); } } callback(error, null); }); } function findUserById(id, callback) { conn.query("SELECT * FROM users WHERE user_uuid='' || $1 LIMIT 1", [id], function (error, result) { if (result.rowCount > 0) { //update user_uuid = result.rows[0].user_uuid; local_email = result.rows[0].local_email; local_password = result.rows[0].local_password; callback(null, user_uuid); } else { callback(null, null); } }); } function save(callback) { conn.query("SELECT * FROM users WHERE user_uuid='' || $1", [user_uuid], function (error, result) { if (error) throw error; if (result.rowCount > 0) { //update conn.query("UPDATE users SET local_email=$1, local_password=$2 WHERE user_uuid=$3", [local_email, local_password, user_uuid], function (error, result) { if (error) throw error; callback(error); }) } else { //insert conn.query("INSERT INTO users (user_uuid, local_email, local_password) VALUES ($1, $2, $3)", [require('node-uuid').v1(), local_email, local_password], function (error, result) { if (error) throw error; callback(error); }) } }) } return { user_uuid: user_uuid, local: { email: local_email, password: local_password }, facebook: { id: null, token: null, email: null, name: null }, twitter: { id: null, token: null, displayName: null, username: null }, google: { id: null, token: null, email: null, name: null }, generateHash: generateHash, validPassword: validPassword, findUserByEmail: findUserByEmail, findUserById: findUserById, save: save } }; 

为什么我的内部.save函数不能访问在构造函数中设置的local_email和local_passwordvariables?

你将不得不在你的保存function中使用this.local.local_email (和密码)。 这是推理:

在你的构造函数中,你有local_emaillocal_password局部variables – 这些是你在save函数中访问的variables; 当保存被调用时,它会检查本地作用域( save自己的作用域,并且由于这些variables不存在,它将检查下一个作用域 – 构造函数作用域。

现在,你也有返回的对象,其中local.local_email作为一个属性。 当构造函数被调用时,这个属性被设置为undefined (如果我正确地遵循逻辑)。 稍后设置时,该更改只发生在该对象的属性上 。 它不会reflection回构造函数的本地local_email

所以,你的函数正在访问一个局部variables,而你正在设置一个对象的属性的新值。

我重写了它,它似乎工作,但我不完全确定为什么要说,我认为在前面的例子中,我正在混合JS OO的不同风格:

 var User=new require('./models').User; var user=new User(); user.findUserById('1', function(err, user) {console.log(user)}); var newUser = new User(); // set the user's local credentials newUser.local_email = 'simon@infoqual.net'; newUser.local_password = newUser.generateHash('hello'); // save the user newUser.save(function(err) { if (err) throw err; console.log(newUser); }); 

这要求:

 exports.User = User; function User() { var user=this; user.user_uuid=null; user.local_email=null; user.local_password=null; user.generateHash=function (password) { return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); } user.validPassword=function (password, password_compare) { return bcrypt.compareSync(password, password_compare); } user.findUserByEmail=function (email, callback) { conn.query("SELECT * FROM users WHERE local_email=$1 LIMIT 1", [email], function (error, result) { //var user = this.User; if (!error) { if (result.rowCount > 0) { user.local_email = result.rows[0].email; user.user_uuid = result.rows[0].user_uuid; //load rest of user obj callback(error, user.user_uuid); } } callback(error, null); }); } user.findUserById=function (id, callback) { conn.query("SELECT * FROM users WHERE user_uuid='' || $1 LIMIT 1", [id], function (error, result) { if (result.rowCount > 0) { //update user.user_uuid = result.rows[0].user_uuid; user.local_email = result.rows[0].local_email; user.local_password = result.rows[0].local_password; callback(null, user.user_uuid); } else { callback(null, null); } }); } user.save=function (callback) { conn.query("SELECT * FROM users WHERE user_uuid='' || $1", [user.user_uuid], function (error, result) { if (error) throw error; if (result.rowCount > 0) { //update conn.query("UPDATE users SET local_email=$1, local_password=$2 WHERE user_uuid=$3", [user.local_email, user.local_password, user.user_uuid], function (error, result) { if (error) throw error; callback(error); }) } else { //insert user.user_uuid=require('node-uuid').v1(); conn.query("INSERT INTO users (user_uuid, local_email, local_password) VALUES ($1, $2, $3)", [user.user_uuid, user.local_email, user.local_password], function (error, result) { if (error) throw error; callback(error); }) } }) } };