| | 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 | }}} |