JavaScript オブジェクト

提供:yonewiki

JAVA Script#リファレンスに戻る。


オブジェクトの機能は、簡単な構造でありながらも、これだけでかなり複雑な操作を実現する仕組みを持っていて、この記事自体はものすごく膨大な量の記事になる予定です。根気よく理解してもらえればと思います。☆Edgeの項目はIEでは動作しない比較的新しい技術です。

宣言と__proto__プロパティ

  • objName1 = new Object;
  • objName1 = new Object();
上記のように記述することでobjName1は空のオブジェクトになります。空といってもObject自体にはいくつかの機能がありますので、objName1にはObjectにぶら下がっている関数やプロパティ値が保持されます。これらの関数やプロパティ値は、ほかの全てのオブジェクトでも保持されているものです。利用可能になっているかどうかはそれぞれのオブジェクトで制御されていることもあります。またメソッドには再定義可能なモノも含まれておりますので、オブジェクトごとに動作が異なることもあります。例えば、どのようなプロパティ値があるのかを示すようなサンプルを以下にしめします。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript 宣言</TITLE>
</HEAD>
<BODY>
JavaScript 宣言<br />
<SCRIPT Language="JavaScript">
<!--
objName1 = new Object();
objName2 = new Object("newって使わない方がいいんじゃね?");

document.write("■Object.__proto__<br />");
document.write(Object.prototype === objName1.__proto__, "<br />");
document.write(objName1, "<br />");

document.write(String.prototype === objName2.__proto__, "<br />");
document.write(objName2, "<br />");

for(var key in objName2){
    document.write("key = ", key , ", Value = ", objName2[key] ,"<br />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


例えば、objName1.__proto__のようなプロパティがあります。このプロパティにはnewキーワードで生成されたオブジェクトのObject.prototypeプロパティ値と同じ値が保持されるものです。objName1自体を出力した場合でも[object Object]のように出力されるのは、prototypeの紐づけが__proto__に格納されているために起こります。サンプルでは、__proto__値は文字として出力はできるような構造ではないため、同じ値になっているかどうかを比較した結果を出力するようにしています。newで生成する際に初期値として文字列を設定したobjName2は自動的にStringオブジェクトと同じ構造が保持されていて、その構造がStringオブジェクトと同等にふるまいます。出力結果はそのことを確認できるものになっています。


このようにObjectには空のObjectでも何かしらの構造を保持していることがわかりましたが、__proto__というイマイチよく理解できないような複雑なプロパティをもっていることもわかってしまいました。この__proto__やprototypeのようなプロパティの仕組みを詳細に解説しようとするとかなり長くなってしまいますが、この複雑さの理解を助けるような記事にするべく、引き続きオブジェクトについての記事を記述していきたいと思います。

constructor プロパティ

  • objName1.constructor
上記のようなプロパティを記述することでobjName1の生成元が返されます。ようするにサンプルのとおりになります。先のサンプルに☆☆☆マークで明記した部分が追加した処理になります。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript constructor</TITLE>
</HEAD>
<BODY>
JavaScript constructor<br />
<SCRIPT Language="JavaScript">
<!--
function funcName(){
    funcName.nValue = 1;
}
objName1 = new Object();
objName2 = new Object("newって使わない方がいいんじゃね?");

document.write("■Object.__proto__<br />");
document.write(Object.prototype === objName1.__proto__, "<br />");
document.write(objName1, "<br />");
document.write("<br />");
document.write("☆☆☆<br />");
document.write(objName1.constructor, "<br />");//☆☆☆
document.write("☆☆☆<br />");
document.write("<br />");

document.write(String.prototype === objName2.__proto__, "<br />");
document.write(objName2, "<br />");

for(var key in objName2){
    document.write("key = ", key , ", Value = ", objName2[key] ,"<br />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

prototype プロパティ

  • Object.prototype.dateToday = "2016/02/23";
上記のようにすることで、ObjectというオブジェクトにdateTodayというプロパティが作成されると同時に値として文字列の2016/02/23が格納されます。したがって、Objectという空のオブジェクトを保持するオブジェクトobjName1のようなオブジェクトにはobjName1.dateTodayというプロパティの参照や値の入れ替えが可能です。サンプルは前述から追加した部分を☆☆☆マークで示しました。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript prototype</TITLE>
</HEAD>
<BODY>
JavaScript prototype<br />
<SCRIPT Language="JavaScript">
<!--
function funcName(){
    funcName.nValue = 1;
}
objName1 = new Object();
objName2 = new Object("newって使わない方がいいんじゃね?");

document.write("■Object.__proto__<br />");
document.write(Object.prototype === objName1.__proto__, "<br />");
document.write(objName1, "<br />");
document.write("<br />");

document.write("☆☆☆<br />");
Object.prototype.dateToday = "2016/02/23";
document.write(objName1.dateToday, "<br />");
document.write("☆☆☆<br />");

document.write("<br />");
document.write(objName1.constructor, "<br />");
document.write(String.prototype === objName2.__proto__, "<br />");
document.write(objName2, "<br />");

for(var key in objName2){
    document.write("key = ", key , ", Value = ", objName2[key] ,"<br />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


上記のようにobjName1オブジェクトを生成してからprototypeによって新しくObjectのプロパティとしてdateTodayを追加したとしても、objName1のdateTodayプロパティの値の保持が反映されます。あんまり役に立たない技術かもしれませんが、こんなこともできるよという程度です。


valueOf() メソッド

  • objName1.valueOf();
objName1の値を出力します。オブジェクト毎に既定の出力値が定まっています。具体的には以下のとおりです。
  • Object Object自身が返却されます。
  • Array 配列の実体が返却されます。
  • Boolean ブール値(false or true)が返却されます。
  • Date 世界協定時のミリ秒が返却されます。
  • Function 関数の内容が返却されます。
  • Number 格納されている数値が返却されます。
  • String 格納されている文字列が返却されます。
より具体的にはサンプルのとおりです。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript .valueOf()</TITLE>
</HEAD>
<BODY>
JavaScript .valueOf()<br />
<SCRIPT Language="JavaScript">
<!--
objObject  = new Object;
objArray   = new Array('1', '2');
objBoolean = new Boolean;
objDate    = new Date;
objFunction= new Function;
objNumber  = new Number(123);
objString  = new String("1234");
with(document){
    write("<TABLE BORDER=\"1\">\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Object.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Object.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objObject.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Array.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Array.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objArray.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Boolean.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Boolean.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objBoolean.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Date.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Date.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objDate.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Function.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Function.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objFunction.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Number.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Number.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objNumber.valueOf());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("String.valueOf()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(String.valueOf());
            write("</TD>\n");
            write("<TD>\n");
                write(objString.valueOf());
            write("</TD>\n");
        write("</TR>\n");
    write("</TABLE>\n");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

toString() メソッド

  • objName1.toString();
objName1の文字列を出力します。オブジェクト毎に既定の出力値が定まっています。具体的には以下のとおりです。
  • Object Object名[object オブジェクト名]の形式で文字列が返却されます。
  • Array 配列の実体を文字列にした形式が返却されます。
  • Boolean ブール値(false or true)が文字列で返却されます。
  • Date 世界協定時をブラウザを使用しているOSのロケールもしくはブラウザに設定されたロケールにしたがって日時の文字列形式にしたものを返却します。
  • Function 関数の内容が文字列で返却されます。
  • Number 格納されている数値が返却されます。引数に基数を指定できます。
  • String 格納されている文字列が返却されます。
  • Error エラーメッセージが文字列で返却されます。
より具体的にはサンプルのとおりです。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript メソッド.toString()</TITLE>
</HEAD>
<BODY>
JavaScript メソッド.toString()<br />
<SCRIPT Language="JavaScript">
<!--
objObject  = new Object;
objArray   = new Array('1', '2');
objBoolean = new Boolean;
objDate    = new Date;
objFunction= new Function;
objNumber  = new Number(123);
objString  = new String("1234");
objError   = new Error("エラーが発生しました。");
with(document){
    write("<TABLE BORDER=\"1\">\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Object.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Object.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objObject.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Array.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Array.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objArray.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Boolean.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Boolean.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objBoolean.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Date.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Date.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objDate.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Function.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Function.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objFunction.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Number.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Number.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objNumber.toString(16));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("String.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(String.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objString.toString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Error.toString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Error.toString());
            write("</TD>\n");
            write("<TD>\n");
                write(objError.toString());
            write("</TD>\n");
        write("</TR>\n");
    write("</TABLE>\n");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


toLocaleString() メソッド

  • objName1.toLocaleString();
objName1のロケール情報に基づいた文字列を出力します。オブジェクト毎に基本的にはtoStringと動作が変わりませんが、DateオブジェクトとNumberオブジェクトのみ日本のロケール情報では既定の出力値が特別に定まっています。具体的には以下のとおりです。
  • Date 世界協定時をブラウザを使用しているOSのロケールもしくはブラウザに設定されたロケールにしたがって日時の文字列形式にしたものを日付の情報のみ返却します。
  • Number 格納されている数値が3桁ごとにカンマで区切られた簿記形式の数値で返却されます。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript メソッド.toLocaleString()</TITLE>
</HEAD>
<BODY>
JavaScript メソッド.toLocaleString()<br />
<SCRIPT Language="JavaScript">
<!--
objObject  = new Object;
objArray   = new Array('1', '2');
objBoolean = new Boolean;
objDate    = new Date;
objFunction= new Function;
objNumber  = new Number(123500);
objString  = new String("1234");
objError   = new Error("エラーが発生しました。");
with(document){
    write("<TABLE BORDER=\"1\">\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Object.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Object.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objObject.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Array.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Array.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objArray.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Boolean.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Boolean.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objBoolean.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Date.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Date.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objDate.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Function.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Function.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objFunction.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Number.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Number.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objNumber.toLocaleString(16));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("String.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(String.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objString.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Error.toLocaleString()\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Error.toLocaleString());
            write("</TD>\n");
            write("<TD>\n");
                write(objError.toLocaleString());
            write("</TD>\n");
        write("</TR>\n");
    write("</TABLE>\n");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


propertyIsEnumerable() メソッド

  • objName1.propertyIsEnumerable(1);
上記のような記述によりオブジェクトがForループのvar a in objName1のような形式で列挙できるかどうかを判定しBoolean値を返却します。特にArrayおよびStringは判定がOKになることが多いです。その他オブジェクトで要素を複数含んでいれば、trueが返却されます。引数にはオブジェクトの要素番号もしくは、プロパティ値を指定することもできます。配列オブジェクトを要素番号で指定する場合は要素番号が存在するかを確認することになります。プロパティ値を指定した場合はForループで列挙できるかを確認します。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript メソッド.propertyIsEnumerable()</TITLE>
</HEAD>
<BODY>
JavaScript メソッド.propertyIsEnumerable()<br />
<SCRIPT Language="JavaScript">
<!--
objObject  = new Object;
objArray   = new Array("HR-V", "ESTIMA", "LEXUS");
objBoolean = new Boolean;
objDate    = new Date;
objFunction= new Function;
objNumber  = new Number(123500);
objString  = new String("1234");
objError   = new Error("エラーが発生しました。");
with(document){
    write("<TABLE BORDER=\"1\">\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Object.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Object.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objObject.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Array.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Array.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objArray.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Boolean.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Boolean.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objBoolean.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Date.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Date.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objDate.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Function.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Function.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objFunction.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Number.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Number.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objNumber.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("String.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(String.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objString.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
        write("<TR>\n");
            write("<TD>\n");
                write("Error.propertyIsEnumerable(1)\n");
            write("</TD>\n");
            write("<TD>\n");
                write(Error.propertyIsEnumerable(1));
            write("</TD>\n");
            write("<TD>\n");
                write(objError.propertyIsEnumerable(1));
            write("</TD>\n");
        write("</TR>\n");
    write("</TABLE>\n");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


prototype.isPrototypeOf() メソッド

  • Object.prototype.isPrototypeOf(objName1);
上記のようにするとObjectのprototypeがobjName1に格納されているか?つまりObject型になっているかを確認するためのメソッドが準備されています。あんまり使わないかもしれませんが、こういうのも覚えておくと意外と役に立つときがあったがりします。ややこしい話を持ち出すのは好きではないのですが、こういうNewキーワードによるオブジェクトの生成結果で__proto__の中にprototypeを割り当てる仕組みをJAVA Script界ではプロトタイプチェーン(prototypechain)と呼んでいます。もっとややこしいことを言うと、C++で言うところのクラスのような仕組みを作ることも可能ですが、それもこれもこのprototypechainの仕組みによって実現されます。あまり内部的な仕組みを理解しようとせず、感覚で使うのもよいと思います。ややこしい話は嫌いですが、ちょこちょこ小出しにして、いつの間にか理解していたっていうのがBESTかなぁと思っています。理解してもらえるかどうかは、未知数ですよね。まぁいい。まぁいい。じっくりやっていこう。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript メソッド.prototype.isPrototypeOf()</TITLE>
</HEAD>
<BODY>
JavaScript メソッド.prototype.isPrototypeOf()<br />
<SCRIPT Language="JavaScript">
<!--
objObject  = new Object;
document.write("■prototype.isPrototypeOf()<BR />");
document.write(Object.prototype.isPrototypeOf(objObject));
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


hasOwnProperty() メソッド

  • objObject.hasOwnProperty(”property_nValue”);
上記のようにすると、objObjectのプロパティ値にprperty_nValueというプロパティが存在するかを評価します。存在すればtrueなければfalseです。この評価はprototypechainを辿らず(この表現は、オブジェクトの中にオブジェクトを持つ構造の子供にあたるオブジェクトまで見るかということを意味しています。)、objObject直下のプロパティとして存在するかを評価します。prototypechainを辿る評価方法としてはinキーワードを使う方法があり、
  • "property_nValue" in objObject
のように記述することで、prototypechainを辿ります。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript メソッド.hasOwnProperty()</TITLE>
</HEAD>
<BODY>
JavaScript メソッド.hasOwnProperty()<br />
<SCRIPT Language="JavaScript">
<!--

function Func1(){
    this.property_nValue1 = 100;
}
function Func2(){
    this.property_nValue2 = 100;
}

Func1.prototype = new Func2();
Func2.prototype.property_nValue3 = 200;

objFunc = new Func1();

document.write("■hasOwnProperty()<BR />");
document.write(objFunc.hasOwnProperty("property_nValue1"), "<BR />");
document.write(objFunc.hasOwnProperty("property_nValue2"), "<BR />");

document.write("<BR />");

document.write("■in<BR />");
document.write("property_nValue1" in objFunc, "<BR />");
document.write("property_nValue2" in objFunc, "<BR />");
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


ソースオブジェクト オブジェクト初期化子

  • var objSource1 = {a:1,b:2};
上記のようにするとobjSource1.a = 1、objSource1.b =2のように初期化されたオブジェクトが生成されます。{}で囲われたオブジェクトを変数に代入するような、こういったものをソースオブジェクトと呼んでいて、test1:1のようにしてプロパティ値を設定するときの:をオブジェクト初期化子と呼びます。オブジェクトなので{}中は構造的なモノだけを指定します。プログラムを記述する部分では無いことに注意してください。プロパティ値に関数を指定することはできます。このあたりの利用方法はややこしくなってくるのでまた後の方でサンプルを示します。まずは単純なプロパティ値を設定するサンプルを示します。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript ソースオブジェクト オブジェクト初期化子</TITLE>
</HEAD>
<BODY>
JavaScript ソースオブジェクト オブジェクト初期化子<br />
<SCRIPT Language="JavaScript">
<!--
var objSource1 = {
     test1:1,
     test2:2,
     test3:3
};

document.write("■objSource", objSource1 ,"<BR />");
for(var key in objSource1){
document.write("objSource1 key = ", key , ", objSource1[", key,"] = ",objSource1[key],"<BR />");
    
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.assign 関数 ☆Edge

  • objSource3 = Object.assign(objSource1,objSource2);
上記のようにassign関数の引数に二つのオブジェクトを記述して、結合したものをobjSource3に格納するような動作をする関数です。objSource1と2の両方にあるプロパティ値およびメソッドの全てを保持するobjSource3が生成されます。同じプロパティ値があった場合は引数の後ろ側に書かれたオブジェクトが保持している値が優先されて上書きされます。上記の例ではobjSource2の値が保持されます。また、引数の1番目に空のオブジェクト{}を指定すると、objSource2のオブジェクトそのものがobjSource3のオブジェクトになりますので、オブジェクトをコピーするような処理になります。引数1のオブジェクト自体も2番目のオブジェクトと結合した形にアサイン(割り当て)されます。


InternetExplorer(11までの全てのIE)ではサポートされないオブジェクト関数です。JAVA Scriptユーザにはありがたい機能なのですが、普及率を考えると致命的なものがある関数になっています。


EdgeやChromeではサポートされています。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript assign</TITLE>
</HEAD>
<BODY>
JavaScript assign<br />
<SCRIPT Language="JavaScript">
<!--
var objSource1 = {
    test1:1,
    test2:2,
    test3:3
};
var objSource2 = {
    test1:100,
    nValue1:1,
    nValue2:2
};
var objNull = {};

objSource4 = Object.assign({},objSource1);
objSource5 = Object.assign({},objSource2);
objSource3 = Object.assign(objSource1,objSource2);

document.write("■objSource1", objSource1 ,"<BR />");
for(var key in objSource1){
    document.write("objSource1 key = ", key , ", objSource1[", key,"] = ",objSource1[key],"<BR />");
}
document.write("■objSource2", objSource2 ,"<BR />");
for(var key0 in objSource2){
    document.write("objSource2 key = ", key0 , ", objSource2[", key0,"] = ",objSource2[key0],"<BR />");
}
document.write("■objSource3", objSource3 ,"<BR />");
for(var key1 in objSource3){
    document.write("objSource3 key = ", key1 , ", objSource3[", key1,"] = ",objSource3[key1],"<BR />");
}
document.write("■objSource4", objSource5 ,"<BR />");
for(var key2 in objSource4){
    document.write("objSource4 key = ", key2 , ", objSource4[", key2,"] = ",objSource4[key2],"<BR />");
}
document.write("■objSource5", objSource5 ,"<BR />");
for(var key3 in objSource5){
    document.write("objSource5 key = ", key3 , ", objSource5[", key3,"] = ",objSource5[key3],"<BR />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.create 関数

  • objNew1 = Object.create(Object.prototype,objPropertyDescripter);
上記のようにしてオブジェクトを作成できます。第一引数には作成するオブジェクトのプロトタイプを指定できます。上記の例であれば、何も値を保持しないObjectというオブジェクトが持っている構造をもとにしたプロパティ値やメソッドおよび関数を保持した構造に付け加えて、2番目の引数で指定するのはプロパティ記述子というオブジェクトを保持したプロパティ値を持ったオブジェクト(オブジェクト初期化子で定義するプロパティ)です。プロパティ記述子(PropertyDescripter:プロパティデスクリプタ)とは、プロパティの属性を指定するもので、具体的にはサンプルのような形式のものです。引数で指定したプロパティ記述子を反映した第一引数のオブジェクトを生成するのがこの関数の役割でobjNew1として生成されます。第一引数にnullを指定すると、プロトタイプ値は保持されません。Objectのプロトタイプも保持されません。第二引数を省略することは可能です。


プロパティ記述子は、オブジェクト記述子の形式によって定義できますが、プロパティ記述子としての属性を指示するには、このcreate文の引数の中で指定するか、この先で紹介するdefinePropertyおよびdefineProperties関数の引数の中でプロパティ記述子を付与しないと属性値としての機能を持たないです。単純にソースオブジェクトの定義としてwritableやenumerableやconfiguratableといったプロパティ値を指定してもそういった名前のプロパティ値があるだけのオブジェクトとして機能し、プロパティ記述子としての機能は持ちません。きちんと関数を使って制御しましょう。


InternetExplorerの9以降で使えるようになった機能です。古いIEを使うことを強要されるような職場はありますので、あまり汎用性が無いともいえる関数です。JAVA Scriptを個人的に楽しむのは簡単ですが、バージョンによっては全く動作しないというのがイタイっすね。親切なWebコンテンツを提供するのであれば、使ってほしいブラウザをいくつか明記するべきです。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript create</TITLE>
</HEAD>
<BODY>
JavaScript create<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {};
var objCreate  = Object.create(null,            {x:{value:"create_x" ,writable:true}});
var objCreate2 = Object.create(Object.prototype,{x:{value:"create2_x",writable:true}});
var objCreate3 = Object.create(Object.getPrototypeOf(obj),   {x:{value:"create3_x",writable:true}});

obj.newDataProperty = "obj_newDataProperty";

var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");


descriptor.writable = false;
Object.defineProperty(obj, "newDataProperty", descriptor);


var desc = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
var desc1 = Object.getOwnPropertyDescriptor(objCreate, "x");
var desc2 = Object.getOwnPropertyDescriptor(objCreate2, "x");
var desc3 = Object.getOwnPropertyDescriptor(objCreate3, "x");


document.write("■obj.newDataPropertyのプロパティ記述子の出力<br />");
for (var prop in desc) {
    document.write(prop + ': ' + desc[prop]);
    document.write("<br />");
}

document.write("■objCreate.xのプロパティ記述子の出力<br />");
for (var prop in desc1) {
    document.write(prop + ': ' + desc1[prop]);
    document.write("<br />");
}

document.write("■objCreate2.xのプロパティ記述子の出力<br />");
for (var prop in desc2) {
    document.write(prop + ': ' + desc2[prop]);
    document.write("<br />");
}

document.write("■objCreate3.xのプロパティ記述子の出力<br />");
for (var prop in desc3) {
    document.write(prop + ': ' + desc3[prop]);
    document.write("<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


サンプルはプロパティ記述子を出力したり、プロパティ記述子の値を設定したりする処理をする部分を追加しているためややこしいことになっていますが、まずはObject.createの使い方だけでも参考にしてもらえればと思います。もうちょい先まで同じサンプルで説明したいとおもっておりますので、もうちょっと先の項目まで読めば、わからなかった部分も理解できると思います。


ここでは、サンプルの10、11、12行目だけ解説しておきたいと思います。10行目では生成するオブジェクトを指定しないパターンで、nullとしています。prototypeを持たないので、最小限のオブジェクトが生成されます。11行目ではObjectのプロトタイプを引き継がさせています。Objectも比較的機能を持たないオブジェクトですので、nullの指定とあまり変わりません。違いは調べていませんので、開発者ツールでぶら下がっているオブジェクトの違いを見てみてほしいですね。12行目は生成したオブジェクトからプロトタイプ情報を取得して、引き継がせる手法になっています。引数にしたobjは何も持たないのでobj.prototypeでは生成できませんが、このようにすると、プロトタイプ情報を設定するため、何もないobjでも大丈夫です。第二引数に指定したプロパティ記述子はすべて同じような内容になっていますが、プロパティ記述子は最大構成でも以下のような構造になります。

{

value:"Data",
writable:true,
enumerable:true,
configurable:true,
set:function(){},
get:function(){}

}

プロパティデスクリプタは、値を意味するvalueプロパティのほか、書き換えを制御するwritableプロパティ、inキーワードによる列挙をするかを制御するenumerableプロパティ、プロパティディスクリプタの変更を制御するconfigurableプロパティ。これにset関数とget関数が利用できます。value,writable,enumerable,configuraleはデータプロパティ、setとgetはアクセサプロパティって呼びます。

.defineProperties 関数

  • Object.defineProperties(objCreate1,{data_x:{value:"x_value",writable:true}});
と上記のように1つめの引数にはオブジェクト記述子とプロパティ記述子を定義したいオブジェクトを記載します。2つめの引数にはオブジェクト記述子とプロパティ記述子の構造を持つオブジェクトを記載します。


InternetExplorerの9以降で使えるようになった機能です。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript create</TITLE>
</HEAD>
<BODY>
JavaScript create<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {};
var objCreate  = Object.create(null,                      {x:{value:"create_x" ,writable:true}});
var objCreate2 = Object.create(Object.prototype,          {x:{value:"create2_x",writable:true}});
var objCreate3 = Object.create(Object.getPrototypeOf(obj),{x:{value:"create3_x",writable:true}});

obj.newDataProperty = "obj_newDataProperty";
var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
descriptor.writable = false;

Object.defineProperties(obj, {
    data_x:{//オブジェクト記述子
        //プロパティ記述子 データプロパティ部
        enumerable:true,
        configurable:true,
        set: function (setValue){//アクセサプロパティ部
            this.new_xValue = setValue;
        },
        get: function (){
            return this.new_xValue;
        }
    },
    data_y:{//オブジェクト記述子
        //プロパティ記述子 データプロパティ部
        enumerable:true,
        configurable:true,
        set: function (setValue){//アクセサプロパティ部
            this.new_yValue = setValue;
        },
        get: function (){
            return this.new_yValue;
        }
    }
});
var descriptor2 = Object.getOwnPropertyDescriptor(obj, "data_x");
descriptor2.set(-7100);

var descriptor3 = Object.getOwnPropertyDescriptor(obj, "data_y");
descriptor3.set(5500);

var desc   = Object.getOwnPropertyDescriptor(obj,       "newDataProperty");
var desc_x = Object.getOwnPropertyDescriptor(obj,       "data_x");
var desc_y = Object.getOwnPropertyDescriptor(obj,       "data_y");
var desc1  = Object.getOwnPropertyDescriptor(objCreate, "x");
var desc2  = Object.getOwnPropertyDescriptor(objCreate2,"x");
var desc3  = Object.getOwnPropertyDescriptor(objCreate3,"x");


document.write("■obj.newDataPropertyのプロパティ記述子の出力<br />");
for (var prop in desc) {
    document.write(prop + ': ' + desc[prop]);
    document.write("<br />");
}
document.write("■obj.data_xのプロパティ記述子の出力<br />");
for (var prop in desc_x) {
    document.write(prop + ': ' + desc_x[prop]);
    document.write("<br />");
}
document.write("desctipter accesa get = ", descriptor2.get(), "<br />");
document.write("■obj.data_yのプロパティ記述子の出力<br />");
for (var prop in desc_y) {
    document.write(prop + ': ' + desc_y[prop]);
    document.write("<br />");
}
document.write("desctipter accesa get = ", descriptor3.get(), "<br />");

document.write("■objCreate.xのプロパティ記述子の出力<br />");
for (var prop in desc1) {
    document.write(prop + ': ' + desc1[prop]);
    document.write("<br />");
}

document.write("■objCreate2.xのプロパティ記述子の出力<br />");
for (var prop in desc2) {
    document.write(prop + ': ' + desc2[prop]);
    document.write("<br />");
}

document.write("■objCreate3.xのプロパティ記述子の出力<br />");
for (var prop in desc3) {
    document.write(prop + ': ' + desc3[prop]);
    document.write("<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


アクセサプロパティを記述した場合、データプロパティのvalueおよびwritableは定義することができません。列挙した際にも自動で初期化されるようなこともなく、この二つのプロパティは定義されません。関数内で複数のプロパティを定義することができるので、このプロパティに対して、個別にプロパティ記述子を付与することになります。

.defineProperty 関数

  • Object.defineProperty(objCreate1,"data_x",propertydescriptor);
前述のdefinePropertiesが複数のオブジェクト記述子に対して、プロパティ記述子を定義するものだったのに対して、definePropertyは一つのオブジェクト記述子に対して、プロパティ記述子を定義するものです。上記の例ではdata_xというオブジェクト記述子で定義したプロパティをobjCreate1オブジェクトにぶら下げると共に、そのプロパティのプロパティ記述子としてprpertydescriptorの値が設定されます。サンプルはcreateの項目でも示したものと同じで、20行目が実際に定義をしている部分になります。descriptorという変数にプロパティ記述子の値を格納し、defineProperty関数の第三引数として適切な形式を得ることができる関数getOwnPropertyDescriptorを利用するところがポイントです。


InternetExplorerの9以降で使えるようになった機能です。


同じサンプルをもう一度掲載しておきます。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript create</TITLE>
</HEAD>
<BODY>
JavaScript create<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {};
var objCreate  = Object.create(null,            {x:{value:"create_x" ,writable:true}});
var objCreate2 = Object.create(Object.prototype,{x:{value:"create2_x",writable:true}});
var objCreate3 = Object.create(Object.getPrototypeOf(obj),   {x:{value:"create3_x",writable:true}});

obj.newDataProperty = "obj_newDataProperty";

var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");


descriptor.writable = false;
Object.defineProperty(obj, "newDataProperty", descriptor);


var desc = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
var desc1 = Object.getOwnPropertyDescriptor(objCreate, "x");
var desc2 = Object.getOwnPropertyDescriptor(objCreate2, "x");
var desc3 = Object.getOwnPropertyDescriptor(objCreate3, "x");


document.write("■obj.newDataPropertyのプロパティ記述子の出力<br />");
for (var prop in desc) {
    document.write(prop + ': ' + desc[prop]);
    document.write("<br />");
}

document.write("■objCreate.xのプロパティ記述子の出力<br />");
for (var prop in desc1) {
    document.write(prop + ': ' + desc1[prop]);
    document.write("<br />");
}

document.write("■objCreate2.xのプロパティ記述子の出力<br />");
for (var prop in desc2) {
    document.write(prop + ': ' + desc2[prop]);
    document.write("<br />");
}

document.write("■objCreate3.xのプロパティ記述子の出力<br />");
for (var prop in desc3) {
    document.write(prop + ': ' + desc3[prop]);
    document.write("<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.getOwnPropertyDescriptor 関数

  • var propertyDescriptor = Object.getOwnPropertyDescriptor(objCreate1,"data_x");
上記のように第一引数に、プロパティ値をもったオブジェクト名を記述し、第二引数に第一引数のオブジェクトが保有するプロパティを記述することで、プロパティに設定されているプロパティ記述子のオブジェクトを取得し、左辺値のオブジェクト変数に設定する。サンプルは先述のサンプルと同じで、利用されている部分は16・23~26行目です。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript create</TITLE>
</HEAD>
<BODY>
JavaScript create<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {};
var objCreate  = Object.create(null,            {x:{value:"create_x" ,writable:true}});
var objCreate2 = Object.create(Object.prototype,{x:{value:"create2_x",writable:true}});
var objCreate3 = Object.create(Object.getPrototypeOf(obj),   {x:{value:"create3_x",writable:true}});

obj.newDataProperty = "obj_newDataProperty";

var descriptor = Object.getOwnPropertyDescriptor(obj, "newDataProperty");


descriptor.writable = false;
Object.defineProperty(obj, "newDataProperty", descriptor);


var desc = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
var desc1 = Object.getOwnPropertyDescriptor(objCreate, "x");
var desc2 = Object.getOwnPropertyDescriptor(objCreate2, "x");
var desc3 = Object.getOwnPropertyDescriptor(objCreate3, "x");


document.write("■obj.newDataPropertyのプロパティ記述子の出力<br />");
for (var prop in desc) {
    document.write(prop + ': ' + desc[prop]);
    document.write("<br />");
}

document.write("■objCreate.xのプロパティ記述子の出力<br />");
for (var prop in desc1) {
    document.write(prop + ': ' + desc1[prop]);
    document.write("<br />");
}

document.write("■objCreate2.xのプロパティ記述子の出力<br />");
for (var prop in desc2) {
    document.write(prop + ': ' + desc2[prop]);
    document.write("<br />");
}

document.write("■objCreate3.xのプロパティ記述子の出力<br />");
for (var prop in desc3) {
    document.write(prop + ': ' + desc3[prop]);
    document.write("<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.getOwnPropertyNames 関数

  • var PropertyName1 = Object.getOwnPropertyNames(objCreate1);
上記のように記述し、第一引数にオブジェクト値を与えることで、引数に指定したオブジェクトが保持しているプロパティ値が左辺値のPropertyName1に格納されます。プロパティ値が複数ある場合は、PropertyName1は配列オブジェクトのような構造になるため、列挙するには、For(var prop in PropertyName1)のようにinキーワードでひとつづつ取り出すことが出来ます。具体的な利用法をしめしたサンプルは以下のとおりです。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript getOwnPropertyNames</TITLE>
</HEAD>
<BODY>
JavaScript getOwnPropertyNames<br />
<SCRIPT Language="JavaScript">
<!--
function objFunc(){
    this.nValue1 = 300;
    this.nValue2 = "ECMA Script";
    this.nValue3 = "JScript";
}
var obj = {};
var objCreate  = Object.create(null,                       {x:{value:"create_x" ,writable:true}});
var objCreate2 = Object.create(Object.prototype,           {x:{value:"create2_x",writable:true}});
var objCreate3 = Object.create(Object.getPrototypeOf(obj), {x:{value:"create3_x",writable:true}});

var objFuncName0 = new objFunc();

obj.newDataProperty = "obj_newDataProperty";


var PropertyName0 = Object.getOwnPropertyNames(obj);
var PropertyName1 = Object.getOwnPropertyNames(objCreate);
var PropertyName2 = Object.getOwnPropertyNames(objCreate2);
var PropertyName3 = Object.getOwnPropertyNames(objCreate3);
var PropertyName4 = Object.getOwnPropertyNames(objFuncName0);


var desc  = Object.getOwnPropertyDescriptor(obj, "newDataProperty");
var desc1 = Object.getOwnPropertyDescriptor(objCreate, "x");
var desc2 = Object.getOwnPropertyDescriptor(objCreate2, "x");
var desc3 = Object.getOwnPropertyDescriptor(objCreate3, "x");


document.write("■objの値<br />");
for(var prop in PropertyName0){
    document.write(prop + ': ' + PropertyName0[prop]);
    document.write("<br />");
}
document.write("■objCreateの値<br />");
for(var prop in PropertyName1){
    document.write(prop + ': ' + PropertyName1[prop]);
    document.write("<br />");
}
document.write("■objCreate2の値<br />");
for(var prop in PropertyName2){
    document.write(prop + ': ' + PropertyName2[prop]);
    document.write("<br />");
}
document.write("■objCreate3の値<br />");
for(var prop in PropertyName3){
    document.write(prop + ': ' + PropertyName3[prop]);
    document.write("<br />");
}
document.write("■objFuncName0の値<br />");
for(var prop in PropertyName4){
    document.write(prop + ': ' + PropertyName4[prop]);
    document.write("<br />");
}

document.write("■obj.newDataPropertyのプロパティ記述子の出力<br />");
for (var prop in desc) {
    document.write(prop + ': ' + desc[prop]);
    document.write("<br />");
}

document.write("■objCreate.xのプロパティ記述子の出力<br />");
for (var prop in desc1) {
    document.write(prop + ': ' + desc1[prop]);
    document.write("<br />");
}

document.write("■objCreate2.xのプロパティ記述子の出力<br />");
for (var prop in desc2) {
    document.write(prop + ': ' + desc2[prop]);
    document.write("<br />");
}

document.write("■objCreate3.xのプロパティ記述子の出力<br />");
for (var prop in desc3) {
    document.write(prop + ': ' + desc3[prop]);
    document.write("<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.getOwnPropertySymbols 関数 ☆Edge

この関数は非常に新しい考え方が拡張された結果、生み出された関数であるため、まずはSymbolというオブジェクトが出来たことを理解しなければなりません。Symbolを詳しく説明すると、便利ではあるものの、めったに使わない技術のために小脳に負担をかけて、意識を失うといけないので、ここでは簡単にSymbolというものを説明するに留めます。Symbolはプロパティ値を文字列以外で指定しようとするもので、自由にプロパティ値を追加できるJAVA Scriptの性質で、予期しないプロパティ値の上書きを防ぐことを目的にしています。そして、その極力隠ぺいしようとしたオブジェクトにぶら下がったSymbolを一覧するための関数が、getOwnPropertySymbolsです。

  • var symbols1 = Object.getOwnPropertySymbols(objCrete1);
上記のようにすることで、オブジェクトに定義されているシンボルが一覧されます。シンボルに関する詳細は別の記事で触れる機会があれば、ふれたいと思います。ここでは、プロパティによく似たものでシンボルってのがあって、それを一覧する関数がオブジェクトには標準装備されているだなっていう程度で理解してもらえれば良いかなと思います。サンプルはそんな思いのサンプルです。わからないことは流しておくのがよいかもしれません。もちろん調べてもらってもよいです。ただ、最近できたばかりの技術で、それほど浸透しているわけでも、必要となる技術でもないです。使えたら便利なんだろうなっていう程度です。覚えておくのがいいに決まっていますが、なんでも覚えたからと言って、優秀なプログラムが作れるとは限らないってことです。使いどころが重要です。


InternetExplorer(11までの全てのIE)ではサポートされないオブジェクト関数です。JAVA Scriptユーザにはありがたい機能なのですが、普及率を考えると致命的なものがある関数になっています。


EdgeやChromeではサポートされています。

サンプル

<HTML>
<HEAD>
<TITLE>JavaScript getOwnPropertySymbols</TITLE>
</HEAD>
<BODY>
JavaScript getOwnPropertySymbols<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {
    value:"data1",
};
var key = Symbol("symbol1");
obj[key] = "symbol_data1";

key = Symbol("symbol2");
obj[key] = "symbol_data2";

var symbols = Object.getOwnPropertySymbols(obj);

document.write("■symbol1", "<BR />");
document.write("obj[symbols[0]] = ", obj[symbols[0]], "<BR />");
document.write("symbols[0].toString() = ", symbols[0].toString(), "<BR />");

document.write("■symbol2", "<BR />");
document.write("obj[symbols[1]] = ", obj[symbols[1]], "<BR />");
document.write("symbols[1].toString() = ", symbols[1].toString(), "<BR />");

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.getPrototypeOf 関数

  • var prototypeCreate1 = Object.getPrototypeOf(objCreate1);
上記のようにプロトタイプ値を取得したいオブジェクト値をgetPrototypeOf関数の引数にすると、左辺値のオブジェクトにプロトタイプが格納されます。プロトタイプ値をどういう具合に利用するかは自由ですが、書き出すのは難しいので、プロトタイプを比較する関数で同じ値を保有しているかを確認したり、プロトタイプをオブジェクトに設定したりして使ってみたりすることができます。新たにプロトタイプをオブジェクトに設定した後で、そのオブジェクトがどのようなプロパティを保持するのかを確認することもできます。そういうことを試してみたのが、以下のサンプルになります。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript getPrototypeOf</TITLE>
</HEAD>
<BODY>
JavaScript getPrototypeOf<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {
    value:"data1",
};

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}

var objCreate1 = new objFunc();

var prototypeCreate1 = Object.getPrototypeOf(objCreate1);

document.write("■Object.getPrototypeOf(objCreate1) vs objCreate1<BR />");
document.write(prototypeCreate1.isPrototypeOf(objCreate1), "<BR />");

Object.setPrototypeOf(obj,objCreate1);

document.write("■obj←objCreate1後 Create1 prototype vs obj prototype<BR />");
document.write(prototypeCreate1.isPrototypeOf(obj), "<BR />");

var prototypeObj = Object.getPrototypeOf(obj);

document.write("■objCreate1 prototype vs obj prototype<BR />");
document.write(prototypeCreate1.isPrototypeOf(obj), "<BR />");
document.write("■obj prototype vs obj prototype<BR />");
document.write(prototypeObj.isPrototypeOf(obj), "<BR />");

document.write("■obj key値,property値<BR />");
for(var property in obj){
    document.write(property, ",",obj[property], "<BR />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


サンプルでは24行目でgetPrototypeOf関数を利用して、objFuncという関数のオブジェクトobjCreate1のprototypeを左辺値のprototypeCreate1に格納しています。そして27行目で取得したprototypeCreate1に備わるメソッドisPrototypeOf()でobjCreate1のprototypeと同じかを評価しています。この評価の結果はもちろんtrueです。それ以降の動作については次の記事で解説します。

.setPrototypeOf 関数

  • Object.setPrototypeOf(obj,objCreate1);
上記のように、第一引数に記述したオブジェクトに第二引数に記述したオブジェクトのプロトタイプがセットされて、オブジェクトに含まれるプロパティ値がセットされる。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript setPrototypeOf</TITLE>
</HEAD>
<BODY>
JavaScript setPrototypeOf<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {
    value:"data1",
};

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}

var objCreate1 = new objFunc();

var prototypeCreate1 = Object.getPrototypeOf(objCreate1);

document.write("■Object.getPrototypeOf(objCreate1) vs objCreate1<BR />");
document.write(prototypeCreate1.isPrototypeOf(objCreate1), "<BR />");

Object.setPrototypeOf(obj,objCreate1);

document.write("■obj←objCreate1後 Create1 prototype vs obj prototype<BR />");
document.write(prototypeCreate1.isPrototypeOf(obj), "<BR />");

var prototypeObj = Object.getPrototypeOf(obj);

document.write("■objCreate1 prototype vs obj prototype<BR />");
document.write(prototypeCreate1.isPrototypeOf(obj), "<BR />");
document.write("■obj prototype vs obj prototype<BR />");
document.write(prototypeObj.isPrototypeOf(obj), "<BR />");

document.write("■obj key値,property値<BR />");
for(var property in obj){
    document.write(property, ",",obj[property], "<BR />");
}
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


27行目でObject.setPropertyOf関数でobjというオブジェクト記述子によって、生成したプロパティ記述子を含むオブジェクトにCreate1という関数オブジェクトのprototypeを設定しています。これにより、objはCreate1のプロトタイプを保持するので、nValue1やnValue2といったプロパティキーとその値が受け継がれます。そして、もともと保有していたオブジェクト記述子によって生成された値も保有しつづけることになります。そのことを示すのが、39行目からのobjの各キー値とobj[キー値]による全プロパティ値の出力です。valueもwritableもenumerableもnValue1もnValue2もすべてのプロパティを保有するオブジェクトになっていることがわかると思います。


このような複雑なprototypeのgetやsetによって関数オブジェクト、ソースオブジェクト、オブジェクト記述子、プロパティ記述を設定したり取得したり書き出したりする操作がどのように実際のプログラムで活用できるのかは、また後の方で紹介できたいいなと思っています。ここでは、なんだかややこしい操作ができるんだな程度まで理解しておけば、この記事を読み進めている現段階としての理解度は十分だと思います。少しづつ理解すれば、いづれはすべてがわかる時が来ます。

.freeze 関数

  • Object.freeze(obj);
と上記のようにすると引数に指定したobjオブジェクトはプロパティ記述子の状態が変化し、writableとconfigurableとがfalseに変化し、objのプロパティ値の追加や変更や削除ができなくなります。その子供のプロパティ値に対する操作には影響がなかったりするので、変更できる部分が残ることにも注意が必要です。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript freeze</TITLE>
</HEAD>
<BODY>
JavaScript freeze<br />
<SCRIPT Language="JavaScript">
<!--
var obj = {
    x:{
        value:"data1",
        writable:true,
        enumerable:true,
        configurable:true
    }
};
Object.defineProperty(obj, "x", {
    writable: true,
    enumerable: true,
    configurable: true
});


function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}

Object.freeze(obj);

//オブジェクトの拡張 フリーズしているため無効
obj.property1 = 100;

var propertydescriptor = Object.getOwnPropertyDescriptor(obj, "x");

for(var property in propertydescriptor){
    document.write("property = ", property, ", propertydescriptor[", property ,"] = ", propertydescriptor[property], "<BR />");
}
document.write("obj.x.value = ", obj.x.value, "<BR />");

obj.x = {
        value:"data2",
    };

document.write("obj.x.value = ", obj.x.value, "<BR />");

delete obj.x;

document.write("obj.x.value = ", obj.x.value, "<BR />");


-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.isFrozen 関数

  • Object.isFrozen(obj000)
上記のようにするとobj000がFreeze状態かを調べることができて、Freeze状態と同等ならtrueとなります。具体的には3つのチェックがなされます。
  1. 拡張不能状態になっているか?
  2. writeble値はfalseか?
  3. configuratable値はfalseか?
3つ全てが成り立っていればtrueとなります。そのことがわかるようなサンプルが以下のようなものになります。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript isFrozen</TITLE>
</HEAD>
<BODY>
JavaScript isFrozen<br />
<SCRIPT Language="JavaScript">
<!--
var obj000 = {
    x000:{
        value:"data000",
    }
};
var obj001 = {
    x001:{
        value:"data001",
    }
};
var obj010 = {
    x010:{
        value:"data010",
    }
};
var obj011 = {
    x011:{
        value:"data011",
    }
};
var obj100 = {
    x100:{
        value:"data100",
    }
};
var obj101 = {
    x101:{
        value:"data101",
    }
};
var obj110 = {
    x110:{
        value:"data110",
    }
};
var obj111 = {
    x111:{
        value:"data111",
    }
};
Object.defineProperty(obj000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj001, "x001", {
    value: "data001",
    writable: false,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj010, "x010", {
    value: "data010",
    writable: false,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj011, "x011", {
    value: "data011",
    writable: false,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj100, "x100", {
    value: "data100",
    writable: true,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj101, "x101", {
    value: "data101",
    writable: true,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj110, "x110", {
    value: "data110",
    writable: true,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj111, "x111", {
    value: "data111",
    writable: true,
    enumerable: true,
    configurable: true
});

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}
document.write("■isFrozen<BR />");
document.write("obj000 = ", Object.isFrozen(obj000), "<BR />");
document.write("obj001 = ", Object.isFrozen(obj001), "<BR />");
document.write("obj010 = ", Object.isFrozen(obj010), "<BR />");
document.write("obj011 = ", Object.isFrozen(obj011), "<BR />");
document.write("obj100 = ", Object.isFrozen(obj100), "<BR />");
document.write("obj101 = ", Object.isFrozen(obj101), "<BR />");
document.write("obj110 = ", Object.isFrozen(obj110), "<BR />");
document.write("obj111 = ", Object.isFrozen(obj111), "<BR />");

Object.preventExtensions(obj000);
Object.preventExtensions(obj001);
Object.preventExtensions(obj010);
Object.preventExtensions(obj011);
Object.preventExtensions(obj100);
Object.preventExtensions(obj101);
Object.preventExtensions(obj110);
Object.preventExtensions(obj111);


document.write("■オブジェクト拡張不能化後のisFrozen<BR />");
document.write("obj000 = ", Object.isFrozen(obj000), "<BR />");
document.write("obj001 = ", Object.isFrozen(obj001), "<BR />");
document.write("obj010 = ", Object.isFrozen(obj010), "<BR />");
document.write("obj011 = ", Object.isFrozen(obj011), "<BR />");
document.write("obj100 = ", Object.isFrozen(obj100), "<BR />");
document.write("obj101 = ", Object.isFrozen(obj101), "<BR />");
document.write("obj110 = ", Object.isFrozen(obj110), "<BR />");
document.write("obj111 = ", Object.isFrozen(obj111), "<BR />");

Object.freeze(obj111);

//オブジェクトの拡張 フリーズしているため無効
obj111.property1 = 100;

var propertydescriptor = Object.getOwnPropertyDescriptor(obj111, "x111");

document.write("■obj111のデータ記述子<BR />");
for(var property in propertydescriptor){
    document.write("property = ", property, ", propertydescriptor[", property ,"] = ", propertydescriptor[property], "<BR />");
}
document.write("■obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");



delete obj000.x000;

document.write("■deleteキーワード使用後、obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");

var propertydescriptor000 = Object.getOwnPropertyDescriptor(obj000, "x000");

document.write("■deleteキーワード使用後、obj000のデータ記述子<BR />");
for(var property in propertydescriptor000){
    document.write("property000 = ", property, ", propertydescriptor000[", property ,"] = ", propertydescriptor000[property], "<BR />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.preventExtensions 関数

  • Object.preventExtensions(obj000);
上記のような指定で、引数のオブジェクトを拡張不能にすることができる関数です。つまり、引数に指定したオブジェクトに対してはプロパティ値を追加することはできなくなります。先述のサンプルでもしれっと使っていますので、そちらのサンプルを参照して下さい。


実際に使用しているのは、一つ前の項目のサンプルの112行目~の8行分です。これにより拡張できなくなっているので、プロパティを追加しようとしても値に変化がないことが確認できます。この項目では、サンプルの記述は省略してしまいます。なんつうか、省エネです。手抜き?いやエコです。エコ。エゴじゃないです。僕はええ子です。プロジェクトA子ではありません。?何言ってんだコイツ。


InternetExplorerの9以降で使えるようになった機能です。

 

.isExtensible 関数

  • Object.isExtensible(obj000)
上記のように引数として付与したオブジェクトにぶら下がっているプロパティが拡張不能になっているかを評価し、拡張可能ならばtrue、拡張不可能ならばfalseを返却する関数です。isFrozenが、拡張不能+writeble:false+configuratable:falseでtrueという評価であるので、できないならtrueという形式をとっているのに対して、こちらは拡張できるならtrueという相反するような評価手法になっていることに注意が必要です。勘違いしないようにしましょう。紛らわしいですが、英語ができる人なら関数名からピンとくるんです。日本人にはつらいよね。先述のサンプルと似ていますが、isExtensibleという評価に変更したサンプルです。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript isExtensible</TITLE>
</HEAD>
<BODY>
JavaScript isExtensible<br />
<SCRIPT Language="JavaScript">
<!--
var obj000 = {
    x000:{
        value:"data000",
    }
};
var obj001 = {
    x001:{
        value:"data001",
    }
};
var obj010 = {
    x010:{
        value:"data010",
    }
};
var obj011 = {
    x011:{
        value:"data011",
    }
};
var obj100 = {
    x100:{
        value:"data100",
    }
};
var obj101 = {
    x101:{
        value:"data101",
    }
};
var obj110 = {
    x110:{
        value:"data110",
    }
};
var obj111 = {
    x111:{
        value:"data111",
    }
};
Object.defineProperty(obj000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj001, "x001", {
    value: "data001",
    writable: false,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj010, "x010", {
    value: "data010",
    writable: false,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj011, "x011", {
    value: "data011",
    writable: false,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj100, "x100", {
    value: "data100",
    writable: true,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj101, "x101", {
    value: "data101",
    writable: true,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj110, "x110", {
    value: "data110",
    writable: true,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj111, "x111", {
    value: "data111",
    writable: true,
    enumerable: true,
    configurable: true
});

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}
document.write("■isExtensible<BR />");
document.write("obj000 = ", Object.isExtensible(obj000), "<BR />");
document.write("obj001 = ", Object.isExtensible(obj001), "<BR />");
document.write("obj010 = ", Object.isExtensible(obj010), "<BR />");
document.write("obj011 = ", Object.isExtensible(obj011), "<BR />");
document.write("obj100 = ", Object.isExtensible(obj100), "<BR />");
document.write("obj101 = ", Object.isExtensible(obj101), "<BR />");
document.write("obj110 = ", Object.isExtensible(obj110), "<BR />");
document.write("obj111 = ", Object.isExtensible(obj111), "<BR />");

Object.preventExtensions(obj000);
Object.preventExtensions(obj001);
Object.preventExtensions(obj010);
Object.preventExtensions(obj011);
Object.preventExtensions(obj100);
Object.preventExtensions(obj101);
Object.preventExtensions(obj110);
Object.preventExtensions(obj111);


document.write("■オブジェクト拡張不能化後のisExtensible<BR />");
document.write("obj000 = ", Object.isExtensible(obj000), "<BR />");
document.write("obj001 = ", Object.isExtensible(obj001), "<BR />");
document.write("obj010 = ", Object.isExtensible(obj010), "<BR />");
document.write("obj011 = ", Object.isExtensible(obj011), "<BR />");
document.write("obj100 = ", Object.isExtensible(obj100), "<BR />");
document.write("obj101 = ", Object.isExtensible(obj101), "<BR />");
document.write("obj110 = ", Object.isExtensible(obj110), "<BR />");
document.write("obj111 = ", Object.isExtensible(obj111), "<BR />");

Object.freeze(obj111);

//オブジェクトの拡張 フリーズしているため無効
obj111.property1 = 100;

var propertydescriptor = Object.getOwnPropertyDescriptor(obj111, "x111");

document.write("■obj111のデータ記述子<BR />");
for(var property in propertydescriptor){
    document.write("property = ", property, ", propertydescriptor[", property ,"] = ", propertydescriptor[property], "<BR />");
}
document.write("■obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");



delete obj000.x000;

document.write("■deleteキーワード使用後、obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");

var propertydescriptor000 = Object.getOwnPropertyDescriptor(obj000, "x000");

document.write("■deleteキーワード使用後、obj000のデータ記述子<BR />");
for(var property in propertydescriptor000){
    document.write("property000 = ", property, ", propertydescriptor000[", property ,"] = ", propertydescriptor000[property], "<BR />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.seal 関数

  • Object.seal(obj111);
上記のようにすると引数のオブジェクトがプロパティ拡張不可になり、プロパティの追加はできなくなり、属性の変更もできなくなります。サンプルはそのことを示すサンプルになっています。既存のプロパティ値の変更はできます。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript seal</TITLE>
</HEAD>
<BODY>
JavaScript seal<br />
<SCRIPT Language="JavaScript">
<!--
var obj000 = {
    x000:{
        value:"data000",
    }
};
var obj001 = {
    x001:{
        value:"data001",
    }
};
var obj010 = {
    x010:{
        value:"data010",
    }
};
var obj011 = {
    x011:{
        value:"data011",
    }
};
var obj100 = {
    x100:{
        value:"data100",
    }
};
var obj101 = {
    x101:{
        value:"data101",
    }
};
var obj110 = {
    x110:{
        value:"data110",
    }
};
var obj111 = {
    x111:{
        value:"data111",
    }
};
Object.defineProperty(obj000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj001, "x001", {
    value: "data001",
    writable: false,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj010, "x010", {
    value: "data010",
    writable: false,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj011, "x011", {
    value: "data011",
    writable: false,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj100, "x100", {
    value: "data100",
    writable: true,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj101, "x101", {
    value: "data101",
    writable: true,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj110, "x110", {
    value: "data110",
    writable: true,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj111, "x111", {
    value: "data111",
    writable: true,
    enumerable: true,
    configurable: true
});

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}
document.write("■isExtensible<BR />");
document.write("obj000 = ", Object.isExtensible(obj000), "<BR />");
document.write("obj001 = ", Object.isExtensible(obj001), "<BR />");
document.write("obj010 = ", Object.isExtensible(obj010), "<BR />");
document.write("obj011 = ", Object.isExtensible(obj011), "<BR />");
document.write("obj100 = ", Object.isExtensible(obj100), "<BR />");
document.write("obj101 = ", Object.isExtensible(obj101), "<BR />");
document.write("obj110 = ", Object.isExtensible(obj110), "<BR />");
document.write("obj111 = ", Object.isExtensible(obj111), "<BR />");

Object.preventExtensions(obj000);
Object.preventExtensions(obj001);
Object.preventExtensions(obj010);
Object.preventExtensions(obj011);
Object.preventExtensions(obj100);
Object.preventExtensions(obj101);
Object.preventExtensions(obj110);
//Object.preventExtensions(obj111);


document.write("■オブジェクト拡張不能化後のisExtensible<BR />");
document.write("obj000 = ", Object.isExtensible(obj000), "<BR />");
document.write("obj001 = ", Object.isExtensible(obj001), "<BR />");
document.write("obj010 = ", Object.isExtensible(obj010), "<BR />");
document.write("obj011 = ", Object.isExtensible(obj011), "<BR />");
document.write("obj100 = ", Object.isExtensible(obj100), "<BR />");
document.write("obj101 = ", Object.isExtensible(obj101), "<BR />");
document.write("obj110 = ", Object.isExtensible(obj110), "<BR />");
document.write("obj111 = ", Object.isExtensible(obj111), "<BR />");

obj111.property1 = 100;

Object.seal(obj111);
document.write("obj111 = ", Object.isExtensible(obj111), "<BR />");

obj111.property2 = 1000;

document.write("■obj111.property2の保持値 拡張できない!<BR />");
document.write("obj111.property2.value = ", obj111.property2, "<BR />");

var propertydescriptor3 = Object.getOwnPropertyDescriptor(obj111, "property1");

document.write("■obj111.property1のデータ記述子<BR />");
for(var property in propertydescriptor3){
    document.write("property = ", property, ", propertydescriptor3[", property ,"] = ", propertydescriptor3[property], "<BR />");
}


obj111.property1 = 200;

document.write("■obj111.property1の保持値 変更はできる!<BR />");
document.write("obj111.property1.value = ", obj111.property1, "<BR />");



var propertydescriptor = Object.getOwnPropertyDescriptor(obj111, "x111");

document.write("■obj111のデータ記述子<BR />");
for(var property in propertydescriptor){
    document.write("property = ", property, ", propertydescriptor[", property ,"] = ", propertydescriptor[property], "<BR />");
}
document.write("■obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");



delete obj000.x000;

document.write("■deleteキーワード使用後、obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");

var propertydescriptor000 = Object.getOwnPropertyDescriptor(obj000, "x000");

document.write("■deleteキーワード使用後、obj000のデータ記述子<BR />");
for(var property in propertydescriptor000){
    document.write("property000 = ", property, ", propertydescriptor000[", property ,"] = ", propertydescriptor000[property], "<BR />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.isSealed 関数

  • Object.isSealed(obj000);
上記のようにすると、引数のオブジェクトでプロパティ値の拡張が不可か?データ記述子のconfiguratableがflaseかを評価し、いずれも不可やfalseであれば、trueとなる関数です。サンプルは、評価している内容がわかりやすいようにしたサンプルです。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript seal</TITLE>
</HEAD>
<BODY>
JavaScript seal<br />
<SCRIPT Language="JavaScript">
<!--
var obj000 = {
    x000:{
        value:"data000",
    }
};
var obj001 = {
    x001:{
        value:"data001",
    }
};
var obj010 = {
    x010:{
        value:"data010",
    }
};
var obj011 = {
    x011:{
        value:"data011",
    }
};
var obj100 = {
    x100:{
        value:"data100",
    }
};
var obj101 = {
    x101:{
        value:"data101",
    }
};
var obj110 = {
    x110:{
        value:"data110",
    }
};
var obj111 = {
    x111:{
        value:"data111",
    }
};
Object.defineProperty(obj000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj001, "x001", {
    value: "data001",
    writable: false,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj010, "x010", {
    value: "data010",
    writable: false,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj011, "x011", {
    value: "data011",
    writable: false,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj100, "x100", {
    value: "data100",
    writable: true,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj101, "x101", {
    value: "data101",
    writable: true,
    enumerable: false,
    configurable: true
});
Object.defineProperty(obj110, "x110", {
    value: "data110",
    writable: true,
    enumerable: true,
    configurable: false
});
Object.defineProperty(obj111, "x111", {
    value: "data111",
    writable: true,
    enumerable: true,
    configurable: true
});

function objFunc(){
    this.nValue1 = 100;
    this.nValue2 = 200;
}
document.write("■isSealed<BR />");
document.write("obj000 = ", Object.isSealed(obj000), "<BR />");
document.write("obj001 = ", Object.isSealed(obj001), "<BR />");
document.write("obj010 = ", Object.isSealed(obj010), "<BR />");
document.write("obj011 = ", Object.isSealed(obj011), "<BR />");
document.write("obj100 = ", Object.isSealed(obj100), "<BR />");
document.write("obj101 = ", Object.isSealed(obj101), "<BR />");
document.write("obj110 = ", Object.isSealed(obj110), "<BR />");
document.write("obj111 = ", Object.isSealed(obj111), "<BR />");

Object.preventExtensions(obj000);
Object.preventExtensions(obj001);
Object.preventExtensions(obj010);
Object.preventExtensions(obj011);
Object.preventExtensions(obj100);
Object.preventExtensions(obj101);
Object.preventExtensions(obj110);
//Object.preventExtensions(obj111);


document.write("■オブジェクト拡張不能化後のisSeal<BR />");
document.write("obj000 = ", Object.isSealed(obj000), "<BR />");
document.write("obj001 = ", Object.isSealed(obj001), "<BR />");
document.write("obj010 = ", Object.isSealed(obj010), "<BR />");
document.write("obj011 = ", Object.isSealed(obj011), "<BR />");
document.write("obj100 = ", Object.isSealed(obj100), "<BR />");
document.write("obj101 = ", Object.isSealed(obj101), "<BR />");
document.write("obj110 = ", Object.isSealed(obj110), "<BR />");
document.write("obj111 = ", Object.isSealed(obj111), "<BR />");

obj111.property1 = 100;

Object.seal(obj111);
document.write("obj111 = ", Object.isSealed(obj111), "<BR />");

obj111.property2 = 1000;

document.write("■obj111.property2の保持値 拡張できない!<BR />");
document.write("obj111.property2.value = ", obj111.property2, "<BR />");

var propertydescriptor3 = Object.getOwnPropertyDescriptor(obj111, "property1");

document.write("■obj111.property1のデータ記述子<BR />");
for(var property in propertydescriptor3){
    document.write("property = ", property, ", propertydescriptor3[", property ,"] = ", propertydescriptor3[property], "<BR />");
}


obj111.property1 = 200;

document.write("■obj111.property1の保持値 変更はできる!<BR />");
document.write("obj111.property1.value = ", obj111.property1, "<BR />");



var propertydescriptor = Object.getOwnPropertyDescriptor(obj111, "x111");

document.write("■obj111のデータ記述子<BR />");
for(var property in propertydescriptor){
    document.write("property = ", property, ", propertydescriptor[", property ,"] = ", propertydescriptor[property], "<BR />");
}
document.write("■obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");



delete obj000.x000;

document.write("■deleteキーワード使用後、obj000の保持値<BR />");
document.write("obj000.value = ", obj000.x000, "<BR />");

var propertydescriptor000 = Object.getOwnPropertyDescriptor(obj000, "x000");

document.write("■deleteキーワード使用後、obj000のデータ記述子<BR />");
for(var property in propertydescriptor000){
    document.write("property000 = ", property, ", propertydescriptor000[", property ,"] = ", propertydescriptor000[property], "<BR />");
}

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.is 関数 ☆Edge

  • Object.is(obj000, obj111)
上記のようにするとオブジェクトや変数同士の比較ができます。プロパティ値の構造や値が同じであるかをチェックしてくれます。同じオブジェクトであることも重要です。まったく同じ構造でも、分けて定義してあるとどうやっても比較結果はtrueにはなりません。自分で全く同じ構造のオブジェクトを定義してしまった場合とかに比較はうまくいかないことに注意が必要です。サンプルではそのことがわかるようなサンプルにしました。ちなみにIEでは対応していない新技術でEdgeでしか使えないので、今のところ、大きなシェアのもとで動かすスクリプトを組むという観点である場合、あまり実用性はありません。企業なんかで、Edgeや違うブラウザを使うことを前提としているような拘束的なアプリケーションを組むときに活用できると考えていいと思います。自分はシェア80%くらいまでのブラウザで使える技術しか導入しない性分ですので、こういうのを使えるようになるのは、ずいぶんと未来の時代になるまで待たないとだめっぽいです。あとの20%は見殺しにするのかお前は?という意見あるかもしれませんが、そうです。見殺しです。なんなら早く違うブラウザ使えってことを意味するお仕置き程度にも捉えて技術の利用を決断します。その判断を自分自身でするというだけのことです。誰に対して自分の情報を見てほしいか?自分の作った技術を提供したいか?誰かに提供する場合でもそういった判断をします。企業内で作る場合の方が拘束力が高いので新技術の導入は早いですが、大きな会社の場合だと、事業所毎の方針とかも調査したりとかが必要になるのかもしれません。そして、どの事業所に展開されても、あまり支障がないようにしたいとそういう風に考えると思います。調べるのって大変ですが、事前調査って意外と大事です。発注された場合はもっと拘束力が高くなって、そういう注文だったのでそのまま作りましたと言い訳はできますが、無為にダメなスクリプトを作りたくないのでそのあたりは、相談しながら、互いが合意できる着地点を決めます。もめ事がおこるのは嫌です。私は職業プログラマではないので、そういう交渉をする感じです。職業プログラマならいわれたとおりドライなプログラミングをしなければならない苦悩があったりするのかもしれませんね。その辺の事情は実際に職業プログラマの方のサイトで意見を聞いてみてください。2ちゃんねるとかでも、ある程度事情がわかる場合があります。いろんな会社があるんですよ。きっと。


InternetExplorer(11までの全てのIE)ではサポートされないオブジェクト関数です。JAVA Scriptユーザにはありがたい機能なのですが、普及率を考えると致命的なものがある関数になっています。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript is</TITLE>
</HEAD>
<BODY>
JavaScript is<br />
<SCRIPT Language="JavaScript">
<!--
var obj000 = {
    x000:{
        value:"data000",
    }
};
var obj000copy = obj000;
var obj111copy = obj000;

var obj000_2 = {
    x000:{
        value:"data000",
    }
};

var obj111 = {
    x111:{
        value:"data111",
    }
};
var obj000_data000 = {
    x000:{
        value:"data000",
    }
};
var obj111_data000 = {
    x000:{
        value:"data000",
    }
};

var obj000_data000_x2 = {
    x000:{
        value:"data000",
    }
};
var obj000_data000_x1 = {
    x000:{
        value:"data000",
    }
};
var obj111copy_data000 = obj111;

Object.defineProperty(obj111copy_data000, "x000", {
    value: "data000",
    writable: true,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj111copy, "x000", {
    value: "data000",
    writable: true,
    enumerable: true,
    configurable: true
});
Object.defineProperty(obj000copy, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});

Object.defineProperty(obj000_2, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj000_data000_x1, "x1", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj000_data000_x2, "x2", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});

Object.defineProperty(obj000_data000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});
Object.defineProperty(obj111_data000, "x000", {
    value: "data000",
    writable: true,
    enumerable: true,
    configurable: true
});

Object.defineProperty(obj000, "x000", {
    value: "data000",
    writable: false,
    enumerable: false,
    configurable: false
});

Object.defineProperty(obj111, "x111", {
    value: "data111",
    writable: true,
    enumerable: true,
    configurable: true
});


document.write("■is比較 obj000 vs obj111<BR />");
document.write(Object.is(obj000, obj111),"<BR />");

document.write("■is比較 obj000_data000 vs obj111_data000<BR />");
document.write(Object.is(obj000_data000, obj111_data000),"<BR />");

document.write("■is比較 obj000_data000_x1 vs obj000_data000_x2<BR />");
document.write(Object.is(obj000_data000_x1, obj000_data000_x2),"<BR />");

document.write("■is比較 obj000 vs obj000_2<BR />");
document.write(Object.is(obj000, obj000_2),"<BR />");

document.write("■is比較 obj000 vs obj000copy<BR />");
document.write(Object.is(obj000, obj000copy),"<BR />");

document.write("■is比較 obj000 vs obj111copy<BR />");
document.write(Object.is(obj000, obj111copy),"<BR />");

document.write("■is比較 obj000 vs obj111copy_data000<BR />");
document.write(Object.is(obj000, obj111copy_data000),"<BR />");
-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル

.keys 関数

  • var i = Object.keys(obj);
上記のようにして、for構造の中で使うinキーワードと同じようにオブジェクトの要素名のすべてを、左辺値に代入します。代入された変数は複数の要素が含まれていれば配列のようなオブジェクトになり、この左辺値の配列変数をinキーワードや配列番号で要素の中身を取り出したりすることができます。ただし、inキーワードで取り出す要素名と、微妙な違いがあり、抽出される要素が異なることに注意が必要です。普通に使っている分には同じと思ってもらっても問題ないですが、複雑なオブジェクトを扱い始めると変化が生じてきます。そのことがわかるサンプルを以下に示します。


InternetExplorerの9以降で使えるようになった機能です。


サンプル

<HTML>
<HEAD>
<TITLE>JavaScript keys</TITLE>
</HEAD>
<BODY>
JavaScript keys<br />
<SCRIPT Language="JavaScript">
<!--
function funcOutputObjectKeys(obj){
    var keys = Object.keys(obj);
    var n = 0;
    document.write("■Object.keys()による出力<BR />");
    for(var key in keys){
        document.write("key[", n , "] = ", key,", keys[", key, "] = ", keys[key], ", obj[", key, "] = ", obj[keys[key]] , "<BR />");
        n++;
    }
    n = 0;
    document.write("■for(... in ...)による出力<BR />");
    for(var key in obj){
        document.write("obj[", n , "] = ", key,", obj[", key, "] = ", obj[key], "<BR />");
        n++;
    }
    document.write("<BR />");
}
var obj1 = {
    objectdescriptor_a:100,
    objectdescriptor_b:200,
    objectdescriptor_c:300,
    objectdescriptor_d:400
};
funcOutputObjectKeys(obj1);

function obFunc(){
    this.property_a = 100;
    this.property_b = 200;
}
obFunc.prototype.prototype_add_property_c = 300;
obFunc.prototype.prototype_add_property_d = 400;

obj2 = new obFunc();

funcOutputObjectKeys(obj2);

obj3 = Object.create(obj1,{
    create_property_a:{
        value:"create_property_a",
        writable:true,
        enumerable:true,
        configurable:true
    },
    create_property_b:{
        value:"create_property_b",
        writable:true,
        enumerable:true,
        configurable:true
    },
    create_property_c:{
        value:"create_property_c",
        writable:true,
        enumerable:true,
        configurable:true
    }
});

funcOutputObjectKeys(obj3);

-->
</SCRIPT>
</BODY>
</HTML>

実行結果サンプル


Object.createで生成されたオブジェクトは、enumerableが省略されている場合は規定値でfalseになっているため、for(...in...)では列挙されず、Object.keysでは列挙されます。オブジェクトに対してプロトタイプの追加で作成されたpropertyにも違いが発生します。getOwnPropertyNameという関数の項目で記述したようにプロパティ値の取得がぶら下がっているオブジェクトにまで及ぶ抽出方法もありました。適宜使い分けて、オブジェクトの中身を制御する必要があります。

オブジェクト応用

オブジェクトはここまでで言及した仕組みを用いてより実用的なオブジェクト利用方法が見出されそうなことに気づかれた人もいると思います。自分も活用方法をここでさらに言及する予定ですが、イマイチうまく伝える方法が思いついていません。しばらく時間をあけて追記する予定ですが、活用については、それぞれの人が他のややこしい解説のサイトを見るなりして解決してもらえればと思います。ここで解説した内容を理解していれば、ほかのサイトに記述されている有用な記事を読み解くことは可能だと思います。


JAVA Script#リファレンスに戻る。