オブジェクトに対してのメソッド

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトに対してのメソッドを調べてみます。

javascriptのオブジェクトは全てObject.prototypeからプロパティとメソッドを継承しています。
代表的なメソッドを具体的に調べてみます。

toString()

toString()メソッドはオブジェクトの値を表す文字列を返します。
オブジェクトを文字列に変換する必要がある場合、このメソッドを呼び出します。
例えば、配列を文字列に変換すれば、文字列に変換された配列要素のリストが取得できます。

toLocaleString()

このメソッドはオブジェクトを表すローカライズされた文字列を返します。

valueOf()

このメソッドは文字列以外の基本型にオブジェクトを変換する必要があるときに使います。

オブジェクトのシリアライズ

Posted コメントするカテゴリー: javascript

オブジェクトのシリアライズ

javascriptのオブジェクトのシリアライズについて、試してみます。

オブジェクトのシリアライズは、一度シリアライズしたオブジェクトを元に戻せるような文字列に変換します。
他のプログラム言語にもあるように、シリアライズ操作はプログラミングをするうえで要所で使う場面が出てきます。

ネイティブ関数の使用

まず、オブジェクトをシリアライズするケースからです。
javascriptのネイティブ関数として、JSON.stringify()という関数が用意されています。

逆に一度シリアライズした文字列をアンシリアライズ(元に戻す)場合は、
JSON.parse()という関数が用意されています。

実際にシリアライズを試してみます

まずは、検証用オブジェクトをシリアライズして、ブラウザの開発ツールでログ出力してみます。

//テスト用オブジェクトの用意
let test1 = {
	a: '10',
	b: '20',
	get access_a() {
		return this.a;
	}
}

//オブジェクト「test1」をシリアライズします
let s_obj = JSON.stringify(test1);

console.log(s_obj);

//出力結果は、以下のようになる
{"a":"10","b":"20","access_a":"10"}

以上のような出力結果になりました。

次にアンシリアライズを試してみます

上記の例で使用した変数を、そのままアンシリアライズしてみます。

//(先ほどシリアライズした際の変数を使用)アンシリアライズ
let us_obj = JSON.parse(s_obj);

console.log(us_obj);

//出力結果
Object { a: "10", b: "20", access_a: "10" }

出力結果は上記のようになります。
ブラウザごとに出力結果の表示方法は変わるので、見え方は異なりますが、オブジェクトの内容が列挙されます。

JSON形式について

json形式はjavascrptでプログラムする際に頻繁に使用するデータ形式になります。

正式には「Javascript Object notation」という名称になり、javascriptでオブジェクトリテラルや配列リテラルににたデータ形式でデータ構造を表したり、保持したりします。

シリアライズ可能なものと不可能なもの

シリアライズはjavascriptの値を全てサポートしているわけではないです。

次にサポートしているものと、サポートしていないものを整理してみます。

サポートしているもの

オブジェクト
文字列
配列
数値
true
false
null
NaN
Infinity
Dateオブジェクト

サポートされていないもの

Function
RegExp
Error
undefined

オブジェクトの拡張可属性について

Posted コメントするカテゴリー: javascript

オブジェクトの拡張可属性

オブジェクトに対して、新しくプロパティを追加できるかどうかの指定ができます。
この指定のことを拡張可属性と呼びます。

オブジェクトが拡張可かどうかは、ECMAScriptの処理系によって変わってきます。

ES5は組み込みオブジェクトとユーザ定義オブジェクトは拡張可になります。
明示的に拡張不可が設定された場合は拡張不可になります。

拡張可か拡張不可かを調べるには、Object.isExtensible()で調べます。

オブジェクトと拡張不可にするには、Object.preventExtensions()を使います。

オブジェクトの全ての独自プロパティを再定義不可にするには、Object.seal()を使います。
この場合、オブジェクトに新しいプロパティを追加することはできず、
削除することも再定義することもできません。

オブジェクトをロックするには、Object.freeze()を使います。
オブジェクトを拡張不可にしてプロパティの再定義も不可になります。
また、オブジェクトの独自データプロパティを読み出し専用にします。

オブジェクトのクラス属性について

Posted コメントするカテゴリー: javascript

概要

クラス属性について調べてみます。

クラス属性はオブジェクトの型情報を表す文字列です。
この属性は文字列として設定されており、取得の方法は限定的です。

オブジェクトからクラス属性を取得するにはtoString()メソッドを使います。

実際に簡単なコードを書いてみて動作させてみます。

var test1 = {
	a: '10',
	b: '20',
	get access_a() {
		return this.a;
	}
}
console.log(Object.prototype.toString.call(test1));

var test2 = new Object();
console.log(Object.prototype.toString.call(test2));

var test3 = new Array();
console.log(Object.prototype.toString.call(test3));

var test4 = new Date();
console.log(Object.prototype.toString.call(test4));

上記のコードの実行結果をブラウザの開発ツール(コンソール出力)で確認すると、次のようになります。

[object Object]
[object Object]
[object Array]
[object Date]

出力のルールとしては、先頭部分に「[object]」という文字列が必ず出力されており、その後にオブジェクトのクラス属性が出力されます。

オブジェクト属性の種類について

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトの属性には、3種類の属性があり、
オブジェクトの属性ごとに、使用方法や取得方法、設定方法が変わってきます。

いままではオブジェクトの属性を意識せずにサンプルのコードを書いていましたが、属性ごと詳しく違いを調べてみます。

プロトタイプ属性

オブジェクトが生成されるときにプロトタイプ属性が設定され、オブジェクトの生成方法によってプロトタイプの設定のされかたが変わります。オブジェクトリテラルを使って生成する場合
object.prototype
がプロトタイプ属性使われます。

newを使って生成する場合
コンストラクタ関数のprototypeプロパティの値が使われます。

Object.create()を使って生成する場合
Object.create()に渡された最初の引数が使われます。

オブジェクトのプロパティ属性について

Posted コメントするカテゴリー: javascript

概要

オブジェクトのプロパティには属性があります。

属性は大きく分けて「書き込み可能」「列挙可能」「再定義可能」などがあります。

また、アクセサプロパティのゲッターメソッドとセッターメソッドをプロパティ属性として考えるとすると、アクセサプロパティには書き込み可能属性がないと言えます。

データプロパティの属性は、値も属性のひとつとみなし、書き込み可能、列挙可能、再定義可能、の合計4つの属性があると言えます。
(アクセサプロパティには値の属性はないものと考えます)

まとめるとアクセサプロパティは、ゲッター、セッター、列挙可能、再定義可能、の4つの属性があると言えます。

プロパティのメタ属性の取得と設定


上記の概要で書いた4つの属性について、プロパティディスクリプタと呼ばれるオブジェクトを使います。

プロパティディスクリプタはプロパティのメタ属性と言え、データアクセスに対しての取り決めを決定しています。

データプロパティについては、次のようなメタ属性の名前を持ちます。
value
writable
enumerable
configurable
また、アクセサプロパティについては、次のようなメタ属性を持ちます。
get
set
enumerable
configurable
アクセサプロパティは、valueとwritableのメタ属性はありません。

試しに、前回の投稿で書いたサンプルコードに対して、プロパティディスクリプタオブジェクトを取得して試してみます。
var test = {
	a: '10',
	b: '20',
	get access_a() {
		return this.a;
	}
}

//プロパティディスクリプタオブジェクトを使用してtestオブジェクトのプロパティを出力
console.log(Object.getOwnPropertyDescriptor(test, 'a'));
上記のサンプルコードを実行した結果は次のようになります。

{…}

configurable: true

enumerable: true

value: "10"

writable: true

<prototype>: {…}

__defineGetter__: function __defineGetter__()

__defineSetter__: function __defineSetter__()

__lookupGetter__: function __lookupGetter__()

__lookupSetter__: function __lookupSetter__()

constructor: function Object()

hasOwnProperty: function hasOwnProperty()

isPrototypeOf: function isPrototypeOf()

propertyIsEnumerable: function propertyIsEnumerable()

toLocaleString: function toLocaleString()

toSource: function toSource()

toString: function toString()

valueOf: valueOf()

ブラウザの開発ツールの出力なので、出力結果がまとめられている箇所があり、出力結果のオープン/クローズで表示されるので一部抜粋しています。

上記の出力結果では
configurable: true

enumerable: true

value: "10"

writable: true
という先ほどあげたメタ属性についての記述があります。
また、上記の結果から、testオブジェクトのaプロパティは、データプロパティであることがわかります。(get、setが無く、valueやwritable属性が表示されています)

また、getOwnPropertyDescriptor()の処理対象はオブジェクトに対して独自プロパティのみが対象となります。
継承されたプロパティ等は対象ではない為に、継承オブジェクトには明示的にgetOwnPropertyDescriptor()を書く必要があります。

definePropertyについて

ここまでは、getOwnPropertyDescriptorを使ってオブジェクトのプロパティを調べる形でしたが、
オブジェクトのプロパティに対して、属性を設定(変更)するメソッドについても調べてみます。

オブジェクトに対してプロパティの属性を変更するには、
defineProperty
を使います。

書き方は
Object.defineProperty()
という形になり、()内で設定したいオブジェクトと、プロパティ名、それと属性(上記でいうメタ属性)を設定します。

具体的には、次のようになります。
var test = {
	a: '10',
	b: '20',
	get access_a() {
		return this.a;
	}
}

//definePropertyを使用して属性の変更
Object.defineProperty(test, 'a', {
	value: '30',
	writable: false,
});

//testオブジェクトのプロパティaに対し、文字列40を代入する
test.a = '40';

//内容を確認
console.log(test.a); //出力結果「30」
上記の例はtestオブジェクトのプロパティaに対して、メタ属性を変更しています。また、値の設定についても同時に行っています。

出力結果については、「30」と出力され、writableでfalseにしている為、値の代入を行っても書き変わらない挙動になります。

以上のように、オブジェクトのプロパティに対しての属性の設定を簡単に試してみました。

上記以外の命令や書き方があるので、ブログに追記する形で更新いたします。

ゲッターメソッドとセッターメソッド

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトについては、前回の投稿で簡単なオブジェクトの書き方、使い方を例にあげました。

オブジェクトについて、もう少し入り組んだ概念について詰めます。

オブジェクトに対してゲッターとセッターと呼ぶメソッドを指定でき、それぞれプロパティという位置づけで解釈することができます。

また、ゲッターとセッターについては、それぞれアクセサプロパティと、データプロパティという名前で区別して考えることができます。

アクセサプロパティについて

アクセサプロパティは書き込み不可の属性です。

プロパティがゲッターとセッターの両方のメソッドを持つ場合、 読み書き可のプロパティになります。

ゲッターしかない場合は、読み出し専用のプロパティになり、
セッターしかない場合は、書き込み専用のプロパティになります。

また、データプロパティは単純に値のみを持ちます。

簡単な例

具体的なゲッターメソッドは次のように定義します。

//ゲッター
var test = {
	a: '10',
	b: '20',
	get access_a() {
		return this.a;
	}
}

//呼び出す時の書き方
console.log(test.access_a);
この場合は、変数testに対して、ゲッターメソッド「access_a」を定義しています。

access_aを呼び出すと、メソッド内でプロパティaの値が、返されます。

文字通り「get」キーワードを下記、その後にメソッド名と処理を書きます。

次にセッターメソッドの場合は次のように定義します。

//セッター
var test = {
	c: '30',
	d: '40',
	get access_c() {
		return this.c;
	},
	set access_c(value) {

		//わかりやすいように10倍に計算する
		var sub_c = value * 10;

		this.c = sub_c;
	},
}

//呼び出す時の書き方
console.log(test.access_c); //出力結果「30」

//testオブジェクトのセッタプロパティに対して値を代入
test.access_c = 50;

console.log(test.access_c); //出力結果「500」

上記のようにセッターメソッドを使う時は、オブジェクトのプロパティに対して値を代入するように書きます。

例ではわかりやすいように、セッターメソッド内で値を10倍にして返しています。

セッターに値を入れた後に、改めてゲッターメソッドを使うと、出力結果は計算された結果が返ってきます。

オブジェクトのプロパティにアクセスする方法

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトのプロパティにアクセスする方法を試してみます。 簡単な方法として、for in を使ってオブジェクトにアクセスしてみます。 具体的には下記のように書きます。
var test = {a:10, b:20, c:30}

for (hoge in test) {
	console.log("hoge -> " + hoge);
}

//出力結果は次のようになります
hoge -> a
hoge -> b
hoge -> c
上記のようにfor inを使うとオブジェクト内の「プロパティ」にアクセスすることができます。 では、オブジェクト内の「値」にアクセスするにはどうすればよいか、試してみます。
var test = {a:10, b:20, c:30}

for (hoge in test) {
	console.log("hoge -> " + test[hoge]);
}

//出力結果は次のようになります
hoge -> 10
hoge -> 20
hoge -> 30
最初の例と似ていますが、for inで回した値を参照するタイミングで「オブジェクト[プロパティ]」という記述することで内容を取得することが可能になります。 上記の例は必ずしもこう書かないといけないわけではないので、参考例として書いています。 また、オブジェクトが継承されているケースもあるので、プログラムの実装時には挙動に注意が必要です。

オブジェクトの内容を確認する

オブジェクトの内容が、配列、文字列、オブジェクト等、不明な場合は下記のように書いて簡易的に調べることができます。
// 「obj_check」は調べたいオブジェクト
for(let key in obj_check){
    console.log(key + " : " + obj_check[key]);
}
ただし、最近のブラウザの開発ツールはどんどん改善されているので、いちいちコードを書かなくてもオブジェクトの内容を把握できる方法があるかと思います。 簡易的なチェックという認識で使用するとよさそうです。


オブジェクトのプロパティの削除

Posted コメントするカテゴリー: javascript

概要

javascriptでの、オブジェクトのプロパティの削除についてです。

これまでにもこのブログで出てきましたが、オブジェクトのプロパティを削除するには、delete演算子を使います。

前回のオブジェクト生成の例をもとにdelete演算子の挙動をみてみます。

//新規でオブジェクトを生成する
var test = {a:1, b:2}
  
//.で読み出す
console.log(test.a);
  
//[]で読み出す
console.log(test["a"]);

//delete演算子を使って、プロパティ「a」を削除する
delete test.a;

//delete演算子を使って、プロパティ「b」を削除する
delete test[b];

上記の場合、前者の削除の方法は.を使ってプロパティを指定しています。
後者の削除の方法は[]を使ってプロパティを指定しています。
どちらも同じ同様の動きになります。

注意する点としては、継承されたオブジェクトの継承プロパティは削除されないことです。

delete演算子はプロパティの削除が成功した場合にtrueを返します。
delete演算子は、再定義可の属性がfalseになっているプロパティは削除しないです。

また、注意しなければならないのは、use strictモードの場合と非use strictモードの場合で、挙動が異なる点です。
use strictモードでは再定義不可のプロパティを削除するとtype error例外が発生します。
非use strictモードでは同様の削除をするとfalseを返します。

オブジェクトのプロパティ呼び出しについて

Posted コメントするカテゴリー: javascript

概要

オブジェクトのプロパティの呼び出しについてです。

プロパティを呼び出す時の注意点としては、次のような点があります。

・存在しないプロパティから値を取得する
・独自プロパティから値を取得する
・継承したオブジェクトのプロパティから値を取得する
・存在しないオブジェクトからプロパティの値を取得する

上記の点では、存在しないプロパティから値を取得しようとしてもエラーにはならず、undefinedになります。
また、独自プロパティ、継承したオブジェクトのプロパティから値を取得しようとしても存在しないプロパティの場合はundefinedになります。

ただし、存在しないオブジェクトからプロパティを読み出すとエラーになります。(上記4つめのケース)

オブジェクトの継承とプロトタイプオブジェクト、プロトタイプへの参照と代入の挙動について

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトと、オブジェクトの継承、そしてオブジェクトのプロパティへのアクセスについてまとめます。

javascriptのオブジェクトの独自プロパティについては、そのオブジェクトとプロトタイプオブジェクトから継承したプロパティがあります。

オブジェクトのプロパティへのアクセスについて

例としてオブジェクトAの独自プロパティpを参照しようとする場合、
オブジェクトAの独自プロパティpにアクセスします。

この際、独自プロパティpがオブジェクトAに存在しなければ、
オブジェクトAのプロトタイプオブジェクトA'(ここでは便宜上A’とします)のプロパティpがあるかチェックします。

プロトタイプオブジェクトA’が、プロトタイプチェーンにより、さらにプロトタイプオブジェクトが継承されている場合は、その継承しているプロトタイプオブジェクト(オブジェクトA”とします)のプロパティpがあるかチェックします。

上記のような流れで任意のオブジェクトの任意のプロパティへアクセスする挙動になります。

文章にするとわかりにくい面があるので、簡単なイメージ図にしていみました。

オブジェクトのプロパティへ値を代入する場合

上記の例とは反対に、オブジェクトAのプロパティpに対して、値を代入する場合の挙動をまとめます。

参照する場合とは反対に代入する場合は、動きが変わってきます。

まず、オブジェクトAにプロパティpが存在する場合は、
プロパティpの値がそのまま変更されて終了します。
この場合、プロトタイプチェーンで継承されているオブジェクトのプロパティは無関係で影響を受けません。

次に、オブジェクトAにプロパティpが存在しない場合は、
オブジェクトAに対して、プロパティpが新規追加されます。
この場合も、プロトタイプチェーンで継承されているオブジェクトのプロパティは無関係で影響を受けません。


オブジェクトのプロパティを連想配列として解釈する

Posted コメントするカテゴリー: javascript

概要

前回の投稿では、生成したオブジェクトのプロパティにアクセスする方法を書きました。

//新規でオブジェクトを生成する
var test = {a:1, b:2}
 
//.で読み出す
console.log(test.a);
 
//[]で読み出す
console.log(test["a"]);

上記の方法で、2つ目に書いた[]で読み出す方法について、詳しくみてみます。
.で呼び出す方法と[]で呼び出す方法は、どちらも同じ結果を得ることができますが、[]で呼び出す方法については、文字列を使って呼び出していることが特徴的です。

文字列で呼び出すことが特徴なので、オブジェクトを配列と見立てると連想配列として考えることができます。

より、簡単な方法でオブジェクトの中身を確認する

コンソール上で [object Object] という表示になった場合、
以下の方法で内容を確認することができます。

console.log(JSON.stringify(確認したいオブジェクト));

連想配列としてのオブジェクト

連想配列としてのオブジェクトとして考えると、javascript特有の柔軟な配列操作が可能になります。

例えば以下のように、オブジェクトのプロパティ名が動的に変わる場合でも処理がされます。

var test = {a:1, b:2}

//新たなプロパティを指定して値をセット
//例1
test["c"] = 3;

//例2
test["d"] = 4;


//プロパティ名に、動的な変数を使用
var o = 1;
//例3
test["e" + o] = 5;

//例4
test["e" + (o + 1)] = 6;


//プロパティ名に、動的な変数を使用(その2)
var p = 3;
//例5
test["e" + p] = 7;

//例6
test[p] = 8;


//プロパティ名に、動的な変数を使用(その3)
var q = 4;

//例7
test[q] = 9;

//例8
test[q + 4] = 10;


//確認の為、呼び出し
console.log(test["a"]);   //出力結果:1
console.log(test["b"]);   //出力結果:2
console.log(test["c"]);   //出力結果:3
console.log(test["d"]);   //出力結果:4
console.log(test["e1"]);  //出力結果:5
console.log(test["e2"]);  //出力結果:6
console.log(test["e3"]);  //出力結果:7
console.log(test[p]);     //出力結果:8
console.log(test["p"]);   //出力結果:undefined
console.log(test[q]);     //出力結果:9
console.log(test[4]);     //出力結果:9
console.log(test["q"]);   //出力結果:undefined
console.log(test[8]);     //出力結果:10

後半の例6、例7、例8は少し紛らわしく書きました。

例6について

オブジェクトのプロパティを文字列を示すダブルクォートで囲っていないので、
これは単純に配列のn番目に値を代入する動きになります。

その証拠として、例8ではプロパティを単なる数値として直接指定して値を呼び出しても出力結果が「10」という形で取り出せます。

また、例6に対して、

test["p"]

とした場合の出力結果はundefinedになります。

これはtest[p]という(pは数値の3が代入されている)オブジェクトのプロパティへ代入していますが、pは数値の3なので配列の3番目(0はじまりだと4番目)に値を代入している解釈になるので、
文字列としてのtest[“p”]という形で値を取り出そうとしても存在しない為にundefinedになります。

例7について

オブジェクトのプロパティに対して数値を指定している為、
値を参照する際にも、test[“q”]という形で文字列として取り出そうとするとundefinedになります。

例8について

オブジェクトのプロパティが数値の加算になっているので、
配列の添え字として解釈され、問題なく値が取得できます。

オブジェクトのプロパティ読み出しについて

Posted コメントするカテゴリー: javascript

オブジェクトのプロパティを読み出す方法

オブジェクトのプロパティを読み出す方法は、
以前の投稿でも取り上げましたが、次のように書きます。

var test = {a:1, b:2}

//.で読み出す
console.log(test.a);

//[]で読み出す
console.log(test["a"]);

上記はtestオブジェクトを生成し、その中からaというプロパティの値を読み出しています。

オブジェクトのプロパティに値を代入する方法

上記の例とは逆にオブジェクトのプロパティに値を代入する方法は次のように書きます。

//上記で生成したオブジェクトを使用
test.a = 10;

//.で読み出す
console.log(test.a);

test["b"] = 20
//[]で読み出す
console.log(test["b"]);

オブジェクトの生成

Posted コメントするカテゴリー: javascript

概要

javascript内でオブジェクトを生成する方法を試してみます。

オブジェクトの生成の方法は、次のとおりです。

①オブジェクトリテラルを使って生成
②newキーワードを使って生成
③Object.create()を使って生成

③の方法はECMAScript5の言語仕様に則ってプログラミングする場合に有効です。

オブジェクトリテラル

オブジェクトリテラルを使った生成を試してみます。
変数を宣言し、その変数に対して、新規のオブジェクトを生成し、代入します。

オブジェクトリテラルは、中括弧を使い、内部には「プロパティ名」と「値」をペアでカンマ区切りで記述します。
プロパティ名と値はコロンで区切ります。

//オブジェクトリテラルによる生成

//空のオブジェクトを生成する
var testobject = {};
console.log(testobject); //出力結果「Object {  }」

//要素を2つ持つオブジェクトを生成する
var testobject2 = {a:10, b:20};
console.log(testobject2); //出力結果「Object { a: 10, b: 20 }」

//オブジェクト内の要素が他のオブジェクトのデータを扱う場合
var testobject3 = {c:testobject2.a, d:testobject2.b};
console.log(testobject3); //出力結果「Object { c: 10, d: 20 }」

リテラルを使ったオブジェクトで、プロパティ名に予約語を使う場合は注意が必要です。
ECMAScriptのバージョンによって挙動が変わるので、
各バージョンにより、挙動を確かめてプログラムする必要があります。
一般的にはプロパティ名には予約語ではない文字列を割り当てたほうがプログラミングしやすいかもしれないです。

newキーワードを使った生成

new演算子を使ってオブジェクトを生成します。
new演算子のあとに関数呼び出しを記述して、オブジェクトを生成します。
オブジェクトが生成されるときに必ず実行される関数をコンストラクタと呼び、内部で初期化等の動作をします(各関数によって動作が違うので、詳しくはリファレンスを調べる必要があります)

実際の動きについて、簡単なコードを書いて出力結果を確認してみます。

//newキーワードで生成

//空のオブジェクト生成
var testobj1 = new Object();
console.log(testobj1); //出力結果「Object {  }」

//空の配列オブジェクトを生成
var testobj2 = new Array();
console.log(testobj2); //出力結果「Array []」

//日時を扱うオブジェクトを生成
var testobj3 = new Date();
console.log(testobj3); //出力結果「Date 2018-11-14T12:30:02.403Z」

オブジェクト

Posted コメントするカテゴリー: javascript

概要

javascriptのオブジェクトについての概要です。

・オブジェクトは複合型のデータ型になります。
・複数のデータをまとめて保持し、読み書きが可能です。
・データをプロパティとして呼ぶこともある。
・プロパティは原則、文字列として指定する。
・各プロパティ(文字列)に対し、値をマッピングする。
・マッピングしたものには呼び名がつけられる(ハッシュ、連想配列等)

・オブジェクトは、文字列、数値、真偽値(true/false)、null、undefined以外の値になる。
・オブジェクトは可変の振る舞いをする。(値を参照で操作する)

・オブジェクトの操作は、生成、プロパティへの値の代入、読み出し、削除など。
・同名のプロパティはNG。
・プロパティは「名前と値」の組み合わせ。その他「プロパティ属性」という値を持つ。
・プロパティ属性は「書き込み可」「列挙可」「再定義可」がある。

・オブジェクトはオブジェクト属性を持つ。「プロトタイプ」「クラス」「拡張可フラグ」
・オブジェクトは大きく3種類あり、「ネイティブオブジェクト」「ホストオブジェクト」「ユーザ定義オブジェクト」
・プロパティは大きく2種類あり、「独自プロパティ」「継承プロパティ」

javascriptのオブジェクトの特徴

オブジェクト自身のプロパティの他、ほかのオブジェクトのプロパティも「継承」することができる。
継承の対象となるオブジェクトをプロトタイプと呼びます。

オブジェクトの詳細な挙動について

javascriptのプログラムをより深く正確にする為には、
オブジェクトについての理解を深める必要があります。

オブジェクトの詳細な挙動は、一つ一つこのブログで掘り下げて、できるだけサンプルプログラムを書いて、挙動を確かめながら記事化していきます。

文についてまとめ

Posted コメントするカテゴリー: javascript

概要

javascriptの文についてまとめます。

文はまず、式文と宣言文があり、式文は何らかの処理を書くことで作用します。
宣言文は変数や関数を宣言し定義するための文です。

また、実行順序を変更したり制御する為の制御文もあります。
制御文には以下のようなものがあります。
・条件文
if
swich
・ループ文
for
while
・ジャンプ文
break
return
throw

式文

もっとも簡単な文で、変数の代入や、インクリメント、デクリメント、オブジェクトのプロパティ削除のdeleteなども式文として使われます。

複合文

複合文とは文ブロック

{

}

で囲んで記述される文です。
文ブロックは末尾にセミコロンを記述しません。

宣言文

var
function
等の宣言する文が宣言文です。
変数の宣言と関数の宣言を行います。

var

変数を明示的に宣言する文です。

function

関数を明示的に宣言する文です。
javascriptの関数は、次のように宣言する方法

function test() {

}

や、次のように関数を変数に代入する式もあります。

var ftest = function test() {

}

//呼び出す時
ftest();

条件文

指定された式の値に応じて、他の文を実行したり、処理を分岐したりします。
条件文は「if文」や「if else」、「switch文」などあります。

if文

javascriptが条件を判定して、処理を分岐する文です。

if else文

if文と組み合わせて書きます。
これまで何度もサンプルコードを書いてきましたので、詳しい内容は割愛します。

switch文

ある一つの判定要素に対し、条件分岐が多数ある場合に用いる書き方です。
簡単なサンプルを書きます。

var test = 10;

swicth(test) {
	case 1:
		//処理A
		break;
	case 5:
		//処理B
		break;
	case 10:
		//処理C
		break;
	case 15:
		//処理D
		break;
	default:
		//処理E
		break;
}

上記の場合、変数testの値を判定し、処理Cが実行されます。
処理後のbreakを書かなければ、そのまま次の処理(上記の場合は処理D)が実行されます。

if else文のelseを連続的に書くよりは、この書き方のほうが処理のみとおしが立ちやすくなります。

ループ文 – while

とある条件が真の間、処理を繰り返すループです。

ループ文 – do while

とある条件が真の間、処理を繰り返すループです。
while文との違いは、最初の1回目は条件の真偽に関係なく、必ず実行されます。

ループ文 – for

カウンタ変数を持ち、そのカウンタの条件が真の間は処理を繰り返すループです。

ループ文 – for inf

オブジェクトに対して、オブジェクトのプロパティを巡回する時に書きます。

for (var test in testobject) {
	console.log(testobject[test]);
}

のように書きます。
オブジェクトについて深く理解する必要があるので、オブジェクトとプロパティについては、別途堀さげて書きます。

ジャンプ文

ループの処理中に、条件や状態により、処理をジャンプする場合に書きます。
breakやcontinueを使います。

ラベル文

先頭に識別子を書き、その後にコロンを書き、最後に文を記述します。

testlabel:while(1) {
	//ループ内の処理
	
	//ラベルを利用して、ループ処理を実行
	continue testlabel;
}

上記の例はラベル「testlabel」を宣言し、その後のwhileループを割り当てています。
ループ処理内のtestlabelの文が実行されると、ラベルしたwhileが実行されます。
上記のサンプルは極端な例ですが、ラベルの行でジャンプするイメージになります。

break文

ループ処理中に、処理をとめてループを抜ける時に書きます。

continue文

ループ処理中に、continue文より後の処理は実行せず、またループの最初から処理を開始する時に書きます。
一般的には条件文の後に、指定条件の場合にcontinue文を書くケースが多いです。

return文

関数内の処理が完了し、関数を抜けて結果を返す処理として書きます。

throw文

ある例外的な条件やエラーが発生したことを示すシグナルのことです。
次のようにループの処理中に、例外を強制発動することができます。

for (var i=0; i<10; i++) {
	//例外が発生した場合にスローする
	throw new Error("Err");
}

try catch finally文

java言語とよく似ていますが、プログラム中の処理を試み、
例外が発生した場合は、処理をcatchし、全ての処理後にfinallyを実行する文です。

with文

実用性は低いですが、オブジェクトが入れ子になっている場合や、
多数のオブジェクトのプロパティに何度もアクセスする場合に使います。

use strict文

ECMAScript5で導入された指示子です。
この指示子が書かれたプログラムは、厳密なコードであることが要求され、
プログラムもまた厳密に書きます。(とは言っても常に正確に記述することは基本です)

カンマ演算子

Posted コメントするカテゴリー: javascript

概要

一般的にプログラムを書いていると、よく使用するカンマですが、
javascriptではカンマも演算子と解釈するケースがあります。

セパレータとしてのカンマと、演算子としてのカンマがあります。

また、C言語やC++でもカンマ演算子はあります。
言語のできた順からするとCやC++のほうが先になります。
(C言語は1972年頃、C++は1983年頃、javascriptは1995年頃)

カンマ演算子の挙動

カンマ演算子は、左被演算子を評価して、その値を捨て、右被演算子を評価する動きになります。

演算子の実行例

実際にこの演算子について、コーディングして動作を確かめてみます。

//セパレータとしてのカンマ(変数の宣言なので、カンマ演算子では無い)
var x = 10, y = 20, z = 30;

//カンマ演算子としてのカンマ
var ret = (x, y, z);
console.log(ret); //出力結果「30」カンマ区切りの最後の文字列が代入される


//代入処理がされる場合
var ret = x, y, z;
console.log(ret); //出力結果「10」カンマ区切りの最初の文字列が代入される


//加算演算子を含む場合
var ret = (x += 2, y +=3, z += 4);
console.log(ret); //出力結果「34」


//加算演算子を含む場合(括弧をつけない場合)
var ret = x += 2, y +=3, z += 4;
//出力結果は「SyntaxError: unexpected token: '+='」
//javascriptでは、上記の書き方はエラーになる


//インクリメント
var x = 10, y = 20, z = 30;
x++, x++;
console.log(x); //出力結果「12」


//カンマ演算子を二項演算子の左辺に下記、値を代入する
(x, y) = 40;
//出力結果「ReferenceError: invalid assignment left-hand side」
//javascritpの言語仕様としてエラーになる

上記のような結果になります。
「左被演算子を評価して、その値を捨て、右被演算子を評価する」と一言で言っても、括弧の有無で挙動が変わる点に注意が必要です。

void演算子

Posted コメントするカテゴリー: javascript

概要

あまり見慣れないvoid演算子についてまとめます。

void演算子は単項演算子で、オペランド値を廃棄し未定義値を返す動作をします。

実際の使用場面

void演算子は特殊な利用用途以外では、あまりプログラムしません。

働きとして、戻り値がundefineにならなけれならない場合に使用することが多いです。

typeof演算子

Posted コメントするカテゴリー: javascript

概要

typeof演算子についてまとめます。

オペランドは1つのみで演算します。

オペランドの「データ型」(文字列)を返します。

typeof演算子で判定できる値について

typeof演算子は、以下の値を演算(判定)することができます。

undefined
null
true/false
数値
NaN
文字列
関数
ネイティブオブジェクト
ホストオブジェクト

条件演算子

Posted コメントするカテゴリー: javascript

概要

条件演算子は「?:」で記述する演算子です。
一般的にこれは三項演算子と呼ばれ、オペランドを3つ使い演算を行います。
先頭のオペランドの後に「?」を記述し、その後、2つ目のオペランドを記述し、その後「:」に続けて3つ目のオペランドを記述します。

書き方としては、次のようになります。

判定条件 ? 結果1 : 結果2

判定条件がtrueの場合は結果1のオペランドの値を評価し、falseの場合は結果2のオペランドの値を評価します。

三項演算子については、他の言語にもあり、開発時の環境やプログラマによっても意見が分かれるケースがあります。

eval()

Posted コメントするカテゴリー: javascript

概要

eval()について、詳しく調べてみます。

eval()は1つの引数を渡します。
引数として文字列を渡し、それ以外の場合はそのままの値を返します。

引数が解釈できない場合はシンタックスエラー例外になります。
解釈できた場合は、引数を評価します。

実行例1

eval()を呼び出すとき、呼び出したコードの環境変数が使われます。

実際にeval()で呼び出されたコードの変数が使われるかどうか、
例えば、次のようなコードを書いてみます。

var x = "123";

console.log(eval("x"));

出力結果は

123

になり、eval()で「x」という変数を呼び出したことになります。

実行例2

eval()の引数内で変数定義や関数定義も可能です。
また、定義した変数に値を代入することもできます。
例えば、次のようなコードを書いてみます。

var y = "abc";

console.log(eval("y='d'"));

出力結果は

d

という結果になります。
出力結果を確認する為に、console.logを行っていますが、便宜上書いているだけです。

実行例3

eval()での関数定義を試してみます。

eval("function abc() { return 'z'; }");

console.log(abc());

出力結果は

z

という結果になります。

評価式(eval)

Posted コメントするカテゴリー: javascript

概要

javascriptにはソースコード文字列を評価、実行する機能「eval」があります。
このevalはグローバル関数として定義されており、eval()という形で値を評価します。

evalは()内にはいる文字列を評価します。

eval(string)

stringには文字列が入りますが、文字列をそのまま評価するのではなく、動的に評価されます。

簡単に次の例を書いてみます。

console.log(eval("10 + 15"));

出力結果は「25」という結果になります。

では、次のような書き方をするとどうなるか試します。

var test = 30;

console.log(eval(test  + 15));

出力結果は「45」になります。
このように、引数として文字列を渡す場合でも、数値(の式)を渡す場合でも、評価時にjavascriptのコードとして実行される機能をもつことが特徴です。

算術演算と代入演算子

Posted コメントするカテゴリー: javascript

概要

javascriptは算術演算と代入演算子を組み合わせて使用することができます。
例えば二つのオペランドを「+=」という書き方を使って右辺のオペランドを左辺に代入する時、値を加算して代入することが可能です。

サンプル

次のような例を書いてみて動きを確かめます。

var test = 10;

test += 20;

console.log("test -> " + test);

非常に簡単な例ですが、出力結果は「30」と出力されます。
この時に気をつけなければならないのは、上記の例の場合は2つのオペランドが数値であることです。

では、この数値が文字列だった場合、どのような動きになるか試してみます。

var test = '10';

test += '20';

console.log("test -> " + test);

先ほどの例とほとんど同様のコードですが、出力結果は「1020」となります。
代入するタイミングの算術演算子(加算演算子)が、文字列同士を結合する働きをした為です。

代入演算子の種類

代入演算子には、上記の加算演算子の他に、次のような種類があります。

//加算代入演算子
+=

//減算代入演算子
-=

//乗算代入演算子
*=

//除算代入演算子
/=

//剰余代入演算子
%=

//左シフト代入演算子
<<=

//右シフト代入演算子(符号有り)
>>=

//0埋め右シフト代入演算子(符号無し)
>>>=

//ビットごとのAND代入演算子
&=

//ビットごとのOR代入演算子
|=

//ビットごとのXOR代入演算子
^=

それぞれの代入演算子に記載している「=」の前の演算子の性質を持ち、その演算結果を左にあるオペランドに代入する。という働きになります。

代入演算子

Posted コメントするカテゴリー: javascript

概要

javascriptの代入演算子についてです。
これは読んで字のごとく、変数に値を代入する為の演算子で、
これまでのサンプルで当たり前のように使ってきました。

動作について

代入演算子は「=」と記載し、左のオペランドに対し、右のオペランドを代入します。
左側のオペランドは変数、オブジェクトのプロパティです。
右側のオペランドは任意の値(型も任意)です。

代入時に複数の変数に代入することも可能です。

var test;
var test2;

test = test2 = 10;

上記のようにコードを書くと、変数testとtest2にそれぞれ10が入ります。

論理否定演算子

Posted コメントするカテゴリー: javascript

概要

論理否定演算子は

!

で表す単項演算子になります。
一つのオペランドに対して演算を行います。
論理否定演算子が返す値はtrueかfalseのどちらかになります。
通常はif文などの条件式について、条件を反転させた結果を判定する場合に使われます。

論理和演算子

Posted コメントするカテゴリー: javascript

概要

論理和演算子は、2つのオペンランドのうち、一方または両方がtrueになる場合に式全体でtrueを返す演算子です。

式の評価順について

論理和演算子の式の評価は、左側にあるオペランドを評価し、その結果がtrueの場合には右側のオペランドは評価しません。

この性質を利用して関数などの引数のデフォルト値の設定等に使われる場合があります。

function f (a)
{
    //引数aがnullの場合、変数tに1を代入する(デフォルトとして使用)
    var t = a || 1;
}

ただし上記の例の場合、引数aの値の取り扱い方については、意図しない挙動のプログラムになるので、注意が必要です。
javascriptの値として、文字列、数値の他、引数がnull、undefined、NaN等の場合に注意してプログラムする必要があります。

論理演算子 – 論理積演算子

Posted コメントするカテゴリー: javascript

概要

javascriptの論理演算子についてまとめます。

まずは論理積演算子についてです。

論理積演算子は条件式で「&&」と記述して判定します。
条件式の中で2つのオペランドを記述し、それぞれのオペランドがtrueになる場合に式全体でtrueを返します。

また、どちらかのオペランドがfalseになる場合は、他方がtrueでも式全体ではfalseを返します。

実例

簡単な例を書きます。

var testa = 10;
var testb = 20;

//条件式1
if (testa == 10 && testb == 20) {
    console.log(true);
} else {
    console.log(false);
}
//結果、trueと出力される

var testc = 30;
var testd = 40;

//条件式1
if (testc == 10 && testd == 40) {
    console.log(true);
} else {
    console.log(false);
}
//結果、falseと出力される

上記の場合、条件式1のほうは、if文の中の条件式が2つのオペランドともtrueになるので、式全体でtrueを返します。
また、条件式2のほうは、最初のオペランドがfalseになる為、式全体でもfalseを返します。

javascriptは全ての値に対してtrue/falseの評価をすることができます。

falseに評価されるものはnull、undefined、0、-0、NaN、””(空白文字)等です。

式の評価順について

この論理積演算子を考える時、オペランドの左側から判定されています。
この動きをもう少し詳しく調べると、まず左側のオペランドが判定されて、次に右側のオペランドが判定されます。

左側のオペランドがfalseの場合は、式全体としてfalseをすぐに返し、右側のオペランドは評価されない動きをします。

instanceof演算子

Posted コメントするカテゴリー: javascript

概要

instanceof演算子について調べます。
instanceof演算子はオブジェクトがクラスのインスタンスかどうかを判定します。
インスタンスの場合はtrueを返します。

比較する2つのオペランドは、左側はオブジェクト、右側はクラスを指定しなければならないです。

左側のオペランドがオブジェクトではない場合はfalseを返します。
右側のオペランドがクラス(関数)ではない場合は例外が発生します。

javascriptのプロトタイプチェーンという考え方が重要になってきますが、それについては別に調べて記事化します。

in演算子

Posted コメントするカテゴリー: javascript

概要

javascriptのプログラムではあまり見かけない演算子ですが、in演算子についてまとめます。

in演算子は左側の値が右側のオブジェクトのプロパティであればtrueを返します。

演算子の使用上のルール

この演算子を使うには、下記のようなルールがあります。
・左側のオペランドは文字列
・右側のオペランドはオブジェクト

実例1

試しに、次のような例を書いてみます。

//オブジェクト
var testobject = {
	aaa: "test1",
	bbb: "test2",
	ccc: true
};

console.log("aaa" in testobject);
console.log("bbb" in testobject);
console.log("ddd" in testobject);

この場合の結果は、

true
true
false

になります。
オブジェクト「testobject 」に対し、aaaとbbbはプロパティとして存在しますが、dddは存在しない為、falseになります。

実例2

では、オブジェクト中身を変えて、次のような例を試してみます。

//オブジェクト
var testobject2 = [
	10,
	20,
	30
];

console.log("aaa" in testobject2);
console.log(10 in testobject2);
console.log("10" in testobject2);
console.log("11" in testobject2);

この場合の結果は、

false
false
false
false

になりました。
一見すると2つ目の演算結果はtrueになりそうですが、正確には「プロパティが存在するかどうか」が判定基準になるので、全てfalseになりました。

実例3

では、次のような場合はどうなるか、試してみます。

var testobject3 = [10, 11, 12];

console.log("0" in testobject3);
console.log(1 in testobject3);
console.log(3 in testobject3);

この場合の結果は、

true
true
false

になります。
オブジェクトtestobject3は要素の内容だけが書かれていますが、プロパティは明示的に書いていないものの、配列のN番目という判定がされています。
また、2番目の「1」のin演算子については、判定時に文字列の「”1″」として変換されて演算がされるので注意が必要です。

等値演算子と同値演算子

Posted コメントするカテゴリー: javascript

等値演算子についてまとめます。

2つのオペランドを比較し、等しい場合はtrue、等しくない場合はfalseを返します。
等値演算子は同様の演算子として、同値演算子があります。

それぞれの特徴を以下にまとめます。

■等値演算子
・オペランドを比較する際、型変換が行われ値が比較される
・コードは「==」という記述になる
・比較の際、反対の結果を得るには「!=」というコードになる
・オペランドが同じ型の場合は、値が同一かを判定し、等しければtrueを返す
・型が異なる場合は同じ型に変換してから判定する
・どちらか一方がnullの場合、等しいと判定する
・どちらか一方がundefinedの場合、等しいと判定する
・どちらか一方がtrueの場合、1に変換してから比較される
・どちらか一方がfalseの場合、1に変換してから比較される
・どちらか一方がオブジェクトの場合、オブジェクトを基本型に変換して比較される

■同値演算子
・厳密に型まだ考慮して比較される
・型が違う場合は等しくない(false)が返る
・コードは「===」という記述になる
・比較の際、反対の結果を得るには「!==」というコードになる
・オペランドがnull同士の場合、等しいと判定する
・オペランドがundefinedの場合、等しいと判定する
・両方の値が論理値(true)か論理値(false)であれば等しいと判定する
・NaNがオペランドのどちらかにある場合は等しくないと判定する
・NaNがオペランドの両方ある場合も等しくないと判定する
・両方の値が数値の場合で、同じ値である場合は等しいと判定する
・両方の値が数値の場合で、片方が0の場合も等しいと判定する
・両方の値が同じオブジェクトや配列または関数の場合、等しいと判定する
・異なるオブジェクトを参照している場合は等しくないと判定する