以下のようなjsを書きました。
function aaa(name, age) { aaa.test = name; aaa.name=1; console.log(aaa.test); console.log(aaa.name); } aaa(1,2);
結果は
1 aaa
です。
aaa関数の引数と同じ名前のオブジェクト(aaa.name)を作ると、1を代入しても代入されていないようですがこれはどうしてでしょうか。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
根本的にコンストラクタを誤解しています.
あなたが提示したコードは単なる関数の呼び出しであり, 各行の意味合いは次のとおりです.
JavaScript
1//function宣言により変数aaaにFunctionオブジェクトが割り当てられる 2function aaa(name, age) { 3 aaa.test = name;//Functionオブジェクトaaaにプロパティtestを設定している 4 aaa.name=1;//Functionオブジェクトaaaの読み込み専用プロパティnameに値を設定しようとした 5 console.log(aaa.test);//aaa.testにはnameの内容が入っている→1 6 console.log(aaa.name);//aaa.nameには関数としての名称aaaが入っている.→aaa 7} 8aaa(1,2);
一方コンストラクタ関数はnew演算子と共に用いられることでオブジェクトを生成します.
JavaScript
1function Person(name, age){ 2 //コンストラクタ関数内部では生成したオブジェクトに変数thisでアクセスできる 3 //NOTE:この処理をオブジェクトの初期化と呼ぶ 4 this.name = name; 5 this.age = age; 6} 7 8//new演算子を付けてコンストラクタ関数を呼ぶとオブジェクトが返される. 9var person = new Person("山田太郎", 20); 10 11//オブジェクトを使う 12console.log("name", person.name);//name: 山田太郎 13console.log("age", person.age);//age: 20
NOTE:普通の関数とコンストラクタ関数を見分ける方法は?
これらはいずれもfunction
宣言等により定義されるため, どちらの意味合いで使っているのかはコードの文脈を読み解くしかありません. が, 次のように使い分けられていることが多いです.
- 通常の関数は名称が「動詞+目的語」として定義されており, 先頭が小文字である.
例)readBook
「本を読む」関数であることが判る
- コンストラクタ関数の名称はものの名前(カテゴリ)がほとんどであり, 先頭が大文字である.
例)Book
「本」を表すオブジェクトを返すコンストラクタ関数であることが判る
またコードの中で変数this
に対し様々な処理を行っている場合はコンストラクタ関数である可能性が高くなります.(function.bind
メソッドでthis
を束縛している場合を除く)
なおこれでは使い勝手が悪いため, JavaScriptの新版ではコンストラクタ関数専用のclass
宣言が追加されています.
投稿2018/03/21 03:31
編集2018/03/21 05:10総合スコア4756
0
関数のnameプロパティが読み取り専用だからだと思います。
【Function.name - JavaScript | MDN】
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/name
投稿2018/03/21 03:25
総合スコア69400
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
こんにちは。
以下は、kei344さんのご回答をコードを書いて検証するものになります。
説明を分かりやすくするために、aaa
を以下のような中身が空の関数として定義します。
javascript
1function aaa(name, age) { 2 3}
この aaa
は、name
というプロパティを初めから持っており、 その値は "aaa"
という文字列です。
javascript
1console.log(aaa.name); // "aaa" と表示される。 2 3console.log(aaa.name.constructor); // String() あるいは、[Function: String] 等と表示される。
さらに aaa
の name
プロパティは変更することができません。
それはgetOwnPropertyDescriptorを使って、以下のようにして確かめられます。
javascript
1var desc = Object.getOwnPropertyDescriptor(aaa, 'name'); 2 3console.log(desc);
上記を実行すると desc
の内容が以下であることが分かります。
{ value: 'aaa',
writable: false,
enumerable: false,
configurable: true }
このように writable
が false なので、name を書き換えることができません。
javascript
1aaa.name = 'bbb'; 2 3console.log(aaa.name); // => やはり、 "aaa"と表示される。
もし、aaa.name
を書き換えたいのならば、以下のようにして、name
のwritable属性 に
true を設定します。
javascript
1Object.defineProperty(aaa, 'name', { writable: true });
こうしておいて、再度
javascript
1desc = Object.getOwnPropertyDescriptor(aaa, 'name'); 2 3console.log(desc);
とすると、desc
の内容が以下
{ value: 'aaa',
writable: true,
enumerable: false,
configurable: true }
のように、 writable が true になっているのが分かります。こうしておいてから、
aaa.name
に別の文字列を代入することができます。
javascript
1aaa.name = 'bbb'; 2 3console.log(aaa.name); // => "bbb" と表示される。
以上の検証コードを以下に上げておきました。
https://jsfiddle.net/jun68ykt/so1u6nsa/6/
補足
関数オブジェクトに name というプロパティがあって、それは
デフォルトでは書き込みできない、ということは覚えておけばよい
として、質問者様にとってより重要なのは、
「aaa.name
にどうして、1を代入できないのか?」
という質問のタイトルとして、
「コンストラクタがわかりません。」
というのは適切ではない、ということを理解すること
かなと思います。
ですので、 defghi1977さんのご回答も参考のうえ、コンストラクタの定義を
見直して、知識を整理されるとよろしいかと思います。
以上参考になれば幸いです。
投稿2018/03/21 04:30
編集2018/03/22 19:30総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/21 04:50
2018/03/22 23:26 編集
2018/03/25 13:08
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/25 13:08