| 331 | 最後に、メンバの private 宣言に相当するアクセス制約についてですが、 !JavaScript にその為の簡潔な記法が用意されているわけではないものの、それに近いものをクロージャを用いて実現することは可能である、という例を以下に示します。ここまでやるとかなり大きなグループ開発にも耐えうる運用となり得ますが、 !JavaScript 界隈ではあまり見かけない習慣かも知れません。 |
| 332 | |
| 333 | {{{ |
| 334 | var IS_DEBUG = true; |
| 335 | |
| 336 | function Human(name, birth, sex) { |
| 337 | // プライベートフィールド |
| 338 | var fields = { |
| 339 | "name": name, |
| 340 | "birth": birth instanceof Date ? birth : new Date(birth), |
| 341 | "sex": /^m/i.test(sex) ? "male" : "female" |
| 342 | }; |
| 343 | |
| 344 | // メソッドがプライベートフィールドを参照するためのメソッド |
| 345 | this.getFields = function() { |
| 346 | if (IS_DEBUG && !this.permitPrivate()) |
| 347 | throw new Error("private method access denied."); |
| 348 | return fields; |
| 349 | }; |
| 350 | } |
| 351 | |
| 352 | Human.prototype = { |
| 353 | // プライベートメソッドの呼び出し元をチェックしてアクセス許可を判定する |
| 354 | "permitPrivate": function() { |
| 355 | var is_permitted = false; |
| 356 | for (var method in Human.prototype) { |
| 357 | if (Human.prototype[method] == arguments.callee.caller.caller) { |
| 358 | is_permitted = true; |
| 359 | break; |
| 360 | } |
| 361 | } |
| 362 | return is_permitted; |
| 363 | }, |
| 364 | // private: |
| 365 | "getAge": function() { |
| 366 | if (IS_DEBUG && !this.permitPrivate()) |
| 367 | throw new Error("private method access denied."); |
| 368 | var now = new Date(); |
| 369 | var today = now.getFullYear() + ("0" + (now.getMonth() + 1)).slice(-2) + |
| 370 | ("0" + now.getDay()).slice(-2); |
| 371 | var birth = this.getFields().birth; |
| 372 | var birth_day = birth.getFullYear() + ("0" + (birth.getMonth() + 1)).slice(-2) + |
| 373 | ("0" + now.getDay()).slice(-2); |
| 374 | return (today - birth_day) / 10000 | 0; |
| 375 | }, |
| 376 | // public: |
| 377 | "introduce": function() { |
| 378 | var fields = this.getFields(); |
| 379 | alert("私の名前は" + fields.name + "。" + |
| 380 | fields.birth.getFullYear() + "年" + (fields.birth.getMonth() + 1) + "月" + |
| 381 | fields.birth.getDay() + "日生まれの" + this.getAge() + "歳・" + |
| 382 | (fields.sex == "male" ? "男性" : "女性") + "です。"); |
| 383 | } |
| 384 | }; |
| 385 | |
| 386 | var murachi = new Human("村山 俊之", new Date(1978, 1, 7), "male"); |
| 387 | |
| 388 | murachi.introduce(); // 紹介文を表示 |
| 389 | alert(murachi.getAge() + "歳"); // エラー: プライベートメソッドにアクセスできない |
| 390 | }}} |