質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1239閲覧

javascriptでクラス内のメソッドにコンストラクタで定義した変数を使いたい

mote

総合スコア128

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2018/10/25 08:24

編集2018/10/25 08:41

クラス内のメソッドでコンストラクタに初期化した数値を使いたいのですが、
上手くメソッドで使われていません。
nameが定義されていません。
とエラーが出てしまいます
クラスの扱いに慣れていないので、書き方が間違っているのでしょうか?

js

1let MongoClient = require('mongodb').MongoClient; 2let url = "mongodb://localhost:27017/"; 3module.exports = class Mongo{ 4 5 constructor(name,password){ 6 this.name = name ; 7 this.password = password ; 8 } 9 10 registration(){ 11 MongoClient.connect(url,{ useNewUrlParser: true }, function(err, db) { 12 if (err) throw err; 13 let dbo = db.db("mydb"); 14 let myobj = {name : this.name, password : this.password } ; 15 dbo.collection("students").insertOne(myobj, function(err, res) { 16 if (err) throw err; 17 console.log("Number of documents inserted: " + res.insertedCount); 18 db.close(); 19 }); 20 }); 21 return true ; 22 }

↑のregistrationでコンストラクタのnameとpasswordを使いたいのですが使えません

js

1let fs = require("fs") ; 2const Mongo= require("./mongo.js"); 3 4function handler(req,res){ 5 fs.readFile(__dirname+"/index.html",function(err,data){ 6 if(err){ 7 res.writeHead(500); 8 return res.end("Error"); 9 } 10 res.writeHead(200); 11 res.write(data); 12 res.end(); 13 }); 14} 15 16let app = require("http").createServer(handler).listen(3000); 17console.log("server start!"); 18 19let io = require("socket.io").listen(app) ; 20 21io.sockets.on("connection",function(socket){ 22 socket.on("emit_data",function(data){ 23 console.log(data) ; 24 25// 登録ページ、ログインページ 26 let regist = new Mongo(data.name,data.password) ; 27 28 if(regist.registration()){ 29 socket.emit("data_from_server","あなたの名前は「" + 30 regist.name + "」です。" + "あなたのpasswordは「" + 31 regist.password + "」です。") ; 32 } 33 }); 34}); 35

↑恐らく、初期化は上手くいっているとは思います

クライアントからのnameとpassをmongodbのデータベースに送っているのですが、
ソケットを使ってサーバー側に送ると、サーバーコンソールにエラー文が出ます
内容は、

motegiyuuta-no-MacBook-Air:js_template motegiyuta$ node socket.js
server start!
{ name: 'dddddd', password: '123445' }
/Users/motegiyuta/node_modules/mongodb/lib/operations/mongo_client_ops.js:466
throw err;

^

TypeError: Cannot read property 'name' of undefined
at /Users/motegiyuta/Desktop/js_template/mongo.js:14:32
at result (/Users/motegiyuta/node_modules/mongodb/lib/utils.js:414:17)
at executeCallback (/Users/motegiyuta/node_modules/mongodb/lib/utils.js:40
6:9)
at err (/Users/motegiyuta/node_modules/mongodb/lib/operations/mongo_client
_ops.js:286:5)
at connectCallback (/Users/motegiyuta/node_modules/mongodb/lib/operations/
mongo_client_ops.js:241:5)

です。
1つめのjsコードの
let myobj = {name : this.name, password : this.password } ;
でエラーがおきています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dice142

2018/10/25 08:29

エラー文と、どこでエラーが出ているのか記載をお願いします。
mote

2018/10/25 08:42

かしこまりました
guest

回答1

0

ベストアンサー

JavaScript

1 MongoClient.connect(url,{ useNewUrlParser: true }, function(err, db) { 2 if (err) throw err; 3 let dbo = db.db("mydb"); 4 let myobj = {name : this.name, password : this.password } ; 5 dbo.collection("students").insertOne(myobj, function(err, res) { 6 if (err) throw err; 7 console.log("Number of documents inserted: " + res.insertedCount); 8 db.close(); 9 }); 10 });

この1行目のfunction (err, db) {に注目してください。
function () {}は無名関数と言って即興の使い捨て関数を生成する構文ですが、
この{}でthisが再定義されるのでインスタンスとの接続が切り離されます。

他にも色々とありますが、一般的にはこの2つの対策があります。

  • thisが上書きされるので、何か別の変数に保管して貰う
  • ES2015で実装されたアロー関数を利用する

1つ目は昔ながらの手段です。
コールバック関数として切り離されてしまう前に、self変数を宣言してthisを束縛してしまいます。
慣習としてthisを保存する為の変数名としてselfがよく使われるようです。

JavaScript

1 // self変数を宣言 2 var self = this; 3 4 MongoClient.connect(url,{ useNewUrlParser: true }, function(err, db) { 5 if (err) throw err; 6 let dbo = db.db("mydb"); 7 8 // thisは想定外のものになっているので、selfを使ってアクセスする 9 let myobj = {name : self.name, password : this.password } ; 10 11 dbo.collection("students").insertOne(myobj, function(err, res) { 12 if (err) throw err; 13 console.log("Number of documents inserted: " + res.insertedCount); 14 db.close(); 15 }); 16 });

2つ目はアロー関数を利用する方法です。
ES2015で実装されたアロー関数は、ほとんど無名関数のように見えますが、
thisやarguments等の変数を宣言しないという違いがあるので無名関数とは挙動が異なります。

JavaScript

1 MongoClient.connect(url,{ useNewUrlParser: true }, (err, db) => { 2 if (err) throw err; 3 let dbo = db.db("mydb"); 4 5 // thisが上書きされないので、このように堂々と取りに行っても問題ない 6 let myobj = {name : this.name, password : this.password } ; 7 8 dbo.collection("students").insertOne(myobj, (err, res) => { 9 if (err) throw err; 10 console.log("Number of documents inserted: " + res.insertedCount); 11 db.close(); 12 }); 13 });

投稿2018/10/25 10:15

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mote

2018/10/25 10:22

ものすごく分かりやすかったです。 理解が深まりました ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問