タグ「ecmascript5」が付けられているもの

.
EMCAScript5で追加されたObject.definePropertyとObject.keysを確認してみます。

Object.definePropertyは、プロパティの属性enumerableに関係なくキーを配列で返します。
keysはプロパティの属性enumerable=trueのキーのみ返します。
// ビルトインオブジェクトにプロパティを追加
Object.prototype.testMethod = "TESTMETHOD";
Object.defineProperty( Object.prototype, "testMethod2", { enumerable: false });


// Object Literal
console.log("Object Literal ---");
var obj = { id: 1, nickname: "nic" };
Object.defineProperty( obj, "id", { enumerable: false });
console.log( Object.getOwnPropertyNames( obj ) );
console.log( Object.keys( obj ) );
for (var i in obj) {
  console.log(i);
}


// Array Literal
console.log("Array Literal ---");
var array = ["a", "b", "c"];
console.log( Object.getOwnPropertyNames( array ) );
console.log( Object.keys( array ) );
for (var i in array) {
  console.log(i);
}


// Object.prototype
console.log("Object.prototype ---");
console.log( Object.getOwnPropertyNames( Object.prototype ) );
console.log( Object.keys( Object.prototype ) );

// Array.prototype
console.log("Array.prototype ---");
console.log( Object.getOwnPropertyNames( Array.prototype ) );
console.log( Object.keys( Object.prototype ) );

js_e5_tm1.png
参考サイト
15.2.3.4 Object.getOwnPropertyNames ( O )
15.2.3.14 Object.keys ( O )
MDN getOwnPropertyNames
MDN keys

[javascript ECMAScript5 メモ] get,set

A.
EMCAScript5では、ゲッター、セッターが追加されました。
以下のような書式で記述します。
// Object Literal
console.log("Object Literal ---");
var obj = { _id: 1,
            get id() {
              return this._id;
            },
            set id(value) {
          if( isNaN(value) ) throw new Error("Not Number");
              this._id = value;
            }
          };
console.log( obj.id );
obj.id = 2;
console.log( obj.id );
console.log( Object.keys( obj ) );


// Object.defineProperty
console.log("Object.defineProperty ---");
var obj2 = {
  _id: 1
}

Object.defineProperty(obj2, "id", {
  enumerable: false,
  configurable: false,
  get : function(){
          return this._id;
        },
  set : function(value){
      if( isNaN(value) ) throw new Error("Not Number");
          this._id = value;
        }
});
console.log( obj2.id );
obj2.id = 2;
console.log( obj2.id );
console.log( Object.keys( obj2 ) );

// Private
console.log("Private ---");
var obj3 = {};
(function () {
  var _id = 1;
  Object.defineProperty(obj3, "id", {
    enumerable: false,
    configurable: false,
    get : function(){
            return _id;
          },
    set : function(value){
      if( isNaN(value) ) throw new Error("Not Number");
            _id = value;
          }
  });

})();
console.log( obj3.id );
obj3.id = 2;
console.log( obj3.id );
console.log( Object.keys( obj3 ) );
js_e5_sg1.png

参考サイト
MDN get
MDN set
ECMA-262 ECMA-262-5 in detail. Chapter 1. Properties and Property Descriptors.

[javascript ECMAScript5] オブジェクトのclone

A.
EMCAScript5では、オブジェクトをcloneする時にその属性にも気をつける必要がある。

hachy.net ECMAScript 5 に追加された新しい関数(Object編)さんのサイトを参考に試してみる。
// add clone function
Object.clone = function (o) {
    var n = Object.create(Object.getPrototypeOf(o));
    var props = Object.getOwnPropertyNames(o);
    var pName;
    for (var p in props) {
        pName = props[p];
        Object.defineProperty(n, pName, Object.getOwnPropertyDescriptor(o, pName));
    };
    return n;
};

// clone test
var obj = Object.create(Object.prototype, {
  id: {
    value: 1,
    configurable: true,
    writable: false,
    enumerable: true
  },
  nickname: {
    enumerable: true,
    configurable: false,
    get : function(){
            console.log("get");
            return this._nickname
          },
    set : function(value){
            console.log("set");
            this._nickname = value
          }
  }
});

console.dir( obj );
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
console.log( Object.getOwnPropertyDescriptor(obj, "nickname") );

console.log("clone+++++++++++++++++");

var obj2 = Object.clone( obj );
console.dir( obj2 );
console.log( Object.getOwnPropertyDescriptor(obj2, "id") );
console.log( Object.getOwnPropertyDescriptor(obj2, "nickname") );
実行結果
js_ecma5_clone_1.png
内部属性も同様な状態でコピーできている事が確認できる。

参考サイト
hachy.net ECMAScript 5 に追加された新しい関数(Object編)
IEBlog ECMAScript 5 Part 1: Reusable Code
A.
Property Descriptorsまわりの動作メモ

1. Object.create Property Descriptorデフォルト値の確認
Object.create時にvalueだけ設定した場合configurable,enumerable,writable の値を確認する
var obj = Object.create(Object.prototype, {
  id: { value: 1 }
});
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
console.dir( obj );
結果(Safari 5.0.3 Mac)
jd_pd_1.png

2. オブジェクトリテラルで作成した場合のProperty Descriptorデフォルト値の確認
var obj = {id: 1};
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
console.dir( obj );
結果(Safari 5.0.3 Mac)
js_pd_2.png

3.ゲッター、セッターを使う場合 value, writableは設定できない
get, setとvalueを同時に設定してみる

var obj = Object.create(Object.prototype, {
  id: {
    value: 1,
    enumerable: true,
    configurable: true,
    get : function(){
            return this._id;
          },
    set : function(value){
            this._id = value;
          },
  }
});
結果(Safari 5.0.3 Mac)
js_pd_3.png

get, setとwritableを同時に設定してみる
var obj = Object.create(Object.prototype, {
  id: {
    writable : true,
    enumerable: true,
    configurable: true,
    get : function(){
            return this._id;
          },
    set : function(value){
            this._id = value;
          },
  }
});
結果(Safari 5.0.3 Mac)
js_pd_4.png

4. preventExtensionsで新たにプロパティが追加できなくなるか?
var obj = Object.create(Object.prototype, {
  id: { value: 1,
        configurable: true,
        writable: true,
        enumerable: true
      }
});

// preventExtensionsを設定
console.log( Object.isExtensible( obj ) );
Object.preventExtensions( obj );
console.log( Object.isExtensible( obj ) );

// definePropertyは可能か
Object.defineProperty(obj, "id", {
  configurable: false
});

// 既存のプロパティの値の変更は可能か
console.log( obj.id );
obj.id = 2;
console.log( obj.id );

// 新しくプロパティを追加できるか?
obj.nickname = "max";
/*
Object.defineProperty(obj, "nickname", {
  value : 1
});
*/
結果(Chrome 10.0.648.126 Mac)
js_pd_5.png

5. sealでpreventExtentionsとconfigurableがどのように変わるか
var obj = Object.create(Object.prototype, {
  id: { value: 1,
        configurable: true,
        writable: true,
        enumerable: true
      }
});

// preventExtensionsを設定
console.log( Object.isExtensible( obj ) );
console.log( Object.isSealed( obj ) );
Object.seal( obj );
console.log( Object.isExtensible( obj ) );
console.log( Object.isSealed( obj ) );


// definePropertyは可能か
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
Object.defineProperty(obj, "id", {
  configurable: true
});
console.log( Object.getOwnPropertyDescriptor(obj, "id") );


// 既存のプロパティの値の変更は可能か
console.log( obj.id );
obj.id = 2;
console.log( obj.id );

// 新しくプロパティを追加できるか?
obj.nickname = "max";
結果(Chrome 10.0.648.126 Mac)
js_pd_6.png

6. freezeでpreventExtentionsとconfigurable,writableがどのように変わるか
  id: { value: 1,
        configurable: true,
        writable: true,
        enumerable: true
      }
});

// preventExtensionsを設定
console.log( Object.isExtensible( obj ) );
console.log( Object.isSealed( obj ) );
console.log( Object.isFrozen( obj ) );
Object.freeze( obj );
console.log( Object.isExtensible( obj ) );
console.log( Object.isSealed( obj ) );
console.log( Object.isFrozen( obj ) );

console.log( Object.getOwnPropertyDescriptor(obj, "id") );

// definePropertyは可能か
/*
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
Object.defineProperty(obj, "id", {
  configurable: true
});
console.log( Object.getOwnPropertyDescriptor(obj, "id") );
*/

// 既存のプロパティの値の変更は可能か
console.log( obj.id );
obj.id = 2;
console.log( obj.id );
結果(Chrome 10.0.648.126 Mac)
js_pd_7.png

参考になるサイト
15.2.3.8 Object.seal ( O )
15.2.3.9 Object.freeze ( O )
ECMA-262-5 in detail. Chapter 1. Properties and Property Descriptors.
ECMAScript 5:The Definitive Slides
prog*sig Chapter 16. JavaScript Objects
MSDN Object.defineProperty Function (JavaScript)
ECMA Script 5 の Property Descriptor について話してきました
ECMAScript 5 に追加された新しい関数(Object編)
枕を欹てて聴く ES5, Property Descriptor解説

[javascript] Q. 識別子とは?

A.
変数や関数、ラベルの名前はあらかじめ決められた命名規則に従って
つける必要があります。

Fifth Edition of ECMA-262 では以下のように定義されています。


1文字目に利用できる文字
UnicodeLetter
$
_
\ UnicodeEscapeSequence

2文字目以降に利用できる
IdentifierStart
UnicodeCombiningMark
UnicodeDigit
UnicodeConnectorPunctuation
\ UnicodeEscapeSequence
UnicodeLetterとは
any character in the Unicode categories "Uppercase letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or "Letter number (Nl)".
Uppercase letter (Lu)は字の大文字
Lowercase letter (Ll)は字の小文字
Titlecase letter (Lt)は見出し文字に使うアルファベット
Modifier letter (Lm)は文字修飾子
Letter number (Nl)はローマ数字

UnicodeCombiningMarkとは
any character in the Unicode categories "Non-spacing mark (Mn)" or "Combining spacing mark (Mc)"
Non-spacing mark (Mn)は、アクセント記号
Combining spacing mark (Mc) 他の文字

UnicodeDigitとは
any character in the Unicode category "Decimal number (Nd)"
Decimal number (Nd)は数字

UnicodeConnectorPunctuationとは
any character in the Unicode category "Connector punctuation (Pc)"
Connector punctuation (Pc)は句読点
になります。

unicodeを意識しないのであれば、
1文字目には、英字、アンダースコア、ドル記号
2文字目以降は、それに加えて数字
で識別子を決めておけば最低限の要件は満たされます。

また、あらかじめJavaScript内で使われているキーワードは利用できません。
どのようなキーワードが利用できないか確認してみましょう。

予約語
break do instanceof typeof
case else new var
catch finally return void
continue for switch while
debugger function this with
default if throw
delete in try


将来的に予約語として使われる可能性があるキーワード
class enum extends super
const export import


Strictモード用に予約されている
implements let private public yield
interface package protected static


その他にもJavaScriptのプログラム実行時にグローバルオブジェクトに追加される
標準グローバルオブジェクトのプロパティやビルトイン関数や実行環境で展開されるプロパティや関数にも注意する必要があります。

参考:Safariで展開されるキーワード
参考:Safariで展開されるキーワード2
参考:Safariで展開されるキーワード3

標準グローバルオブジェクトで追加される使われるキーワードは
以下のようになります。

グローバルオブジェクト/コンストラクタ
Boolean Number String Array
Object Function RegExp Date

グローバルオブジェクト/エラー
Error EvalError RangeError ReferenceError
SyntaxError TypeError URIError

グローバルオブジェクト/非コンストラクタ関数
decodeURI decodeURIComponent encodeURI encodeURIComponent
eval isFinite isNaN parseFloat
parseInt

グローバルオブジェクト/その他
Infinity Math NaN undefined


参考サイト:
ECMAScript web site [雑記] 識別子名に使える文字
MDN JavaScript Reference

[javascript ECMAScript5] Q. Strict Mode

A.
ECMAScript5ではStrictモードが追加されました。
Strictモードではいくつかの機能が制限されたり、
より多くの例外が投げられるようになり、
プログラムのミスがより気づきやすくなりデバックの効率の改善が期待されます。

Strictモードを利用するには文字列リテラルで"use strict" とスクリプトの先頭に記述します。
(Strictモードに対応していないブラウザでもエラーが発生しないように
文字列リテラルで表記する事になっています。)
"use strict";

Firefox 4.0b10で Strictモードを試してみます。

宣言を行っていない変数への代入
"use strict";
a = 1;
js_strict_1.png



書き込み不可のプロパティへの代入
Object.defineProperty(obj, "a", { value : 1,
                                    writable : false,
                                    enumerable : true,
                                    configurable : true});
obj.a = 2;
js_strict_2.png



削除不可のプロパティを削除
var obj = { d:1 };
Object.defineProperty(obj, "b", { value : 1,
                                    writable : false,
                                    enumerable : true,
                                    configurable : false});

delete obj.b;
js_strict_3.png


拡張不可に設定されているオブジェクトを拡張
console.log( Object.isExtensible(obj) );
Object.preventExtensions(obj);
console.log( Object.isExtensible(obj) );
obj.c = 1;
js_strict_4.png


削除不可のプロパティを削除
console.log( Object.isSealed(obj) );
Object.seal(obj);
console.log( Object.isSealed(obj) );
delete obj.d
js_strict_5.png


arguments.calleeは使えない
function test(a){
  arguments.callee;
}
test(1);
js_strict_6.png


use strict中の関数のthisはundefinedになる
function test(){
  console.log( this );
}
test();
js_strict_7.png


オブジェクトリテラルで同じプロパティ名を使う
function test(a){
  arguments.callee;
}
test(1);
js_strict_8.png


8進数リテラルは例外発生
var oct = 011;
js_strict_9.png


undefinedに代入不可
undefined = 1;
js_strict_10.png


NaNには代入できない
NaN = 1;
js_strict_11.png


Infinityには代入できない
Infinity = 1
js_strict_12.png


参考サイト:
MDN Strict モード
ECMAScript 5 strict mode in Firefox 4

[javascript] Q. 変数の宣言したい

A.
JavaScriptで変数を宣言するには var キーワードを使います。
var 識別子;
複数の値を一度に宣言するにはカンマ(,)で区切ります。
var 識別子, 識別子, 識別子;
変数を宣言して、その変数に代入を行ってみます。
var a;
a = "A";
変数の宣言と代入を同時に行ってみます。
var a = "A";
b = "B";
varを付けないで変数を宣言しない場合は厳密には違いがあります。
その違いを確認してみます。

まずは、宣言した変数がどの段階で利用できるようになるのか確認しましょう。

varを付けて宣言した場合
console.log(a); // undefined
var a = "A";
console.log(a); // A
宣言より前で利用できる状態になっています。
これは、varで宣言された場合変数はプログラムが実行される前の段階で
Globalオブジェクトのプロパティに値はundefinedで設定されるからです。

var無し宣言した場合
console.log(a); // ReferenceError: Can't find variable: a
a = "A";
代入の実行段階でGlobalオブジェクトのプロパティに設定するという
意味になるので、実行以前に呼び出すとエラーが発生します。

varで宣言した変数はdeleteできない
var a = "A";
b = "B";
console.log( delete a ); // false
console.log( delete b ); // true
varで宣言した変数はECMAScript3実装の用語で表すと内部属性のDontDelete属性で
Globalオブジェクトのプロパティに設定されます。
この属性が設定されているプロパティは削除する事ができないので
deleteがfalseになります。

ECMAScript5では、オブジェクトの属性が変更できるようになりました。
ECMAScript3のDontDelete属性は、ECMAScript5 Configurableという属性 で表されています。
実際にvarをつけた場合と無しの場合の値を確認してみましょう。
var a = "A";
b = "B";
console.log( Object.getOwnPropertyDescriptor(this, "a") );
console.log( Object.getOwnPropertyDescriptor(this, "b") );
console.log( delete a ); // false
console.log( delete b ); // true
実行結果
js_val_1.png
varを付けた宣言の場合は configurableがfalseになっているのが
確認できます。falseの場合はプロパティの削除はできません。

参考サイト
ECMA-262-5 in detail. Chapter 1. Properties and Property Descriptors.
ECMA-262-3 in detail. Chapter 2. Variable object.
MDN getOwnPropertyDescriptor

[javascript ECMAScript5] Q. indexOf

  • 投稿日:
  • by
A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
indexOfはArrayの中身を検索し見つかったindexを返却します。
見つからなかった場合は -1 が戻り値として返ります。
indexOfは前からlastIndexOfは後ろから探してます。
var a = [1,2,3,4,1,2,3,4];
console.log(a.indexOf(3)); // 2
console.log(a.lastIndexOf(3)); // 6
console.log(a.lastIndexOf(5)); // -1
js_Array_indexof.png

参考サイト:
MDN Array indexOf

[javascript ECMAScript5] Q. reduce()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
reduceは配列の各要素にcallback関数を呼び出します。
第一引数にcallback関数、第二引数に初期値を渡すと
callback関数の第一引数に最初は初期値が2回目からreturnで返された値が
callback関数の第一引数に返されます。
var a = [1,5,10];
function test(previousValue, currentValue, index, array) {
  console.log("-----");
  console.log("index: " + index);
  console.log("previousValue: " + previousValue);
  console.log("currentValue: " + currentValue);
  return previousValue + currentValue;
}

b = a.reduce(test, 0);
console.log(b);
js_Array_reduce.png

参考サイト:
MDN Array reduce

[javascript ECMAScript5] Q. some()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
someは配列の各要素にcallback関数を呼び出します。
callback関数の第一引数は値、第二引数はインデックス、第三引数は元のArrayがそのまま入ってきます。
callback関数内の返り値が一つでも真の場合 trueを返します。
callback関数内の返り値が真の時点で処理が終了します。
var a = [1,5,10,15,20];
function test(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  return element > 10;
}

function test2(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  return element > 100;
}

b = a.some(test);
console.log(b);

c = a.some(test2);
console.log(c);
is_Array_some.png

参考サイト:
MDN Array some

[javascript ECMAScript5] Q. every()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
everyは配列の各要素にcallback関数を呼び出します。
callback関数の第一引数は値、第二引数はインデックス、第三引数は元のArrayがそのまま入ってきます。
callback関数内の返り値がすべて真の場合 trueを返します。
callback関数内の返り値が偽の時点で処理が終了します。
var a = [1,5,10,15,20];
function test(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  return element < 10;
}

function test2(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  return element < 100;
}

b = a.every(test);
console.log(b);

c = a.every(test2);
console.log(c);


js_Array_every.png

参考サイト:
MDN Array every

[javascript ECMAScript5] Q. filter()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
filterは配列の各要素にcallback関数を呼び出します。
callback関数の第一引数は値、第二引数はインデックス、第三引数は元のArrayがそのまま入ってきます。
callback関数の返り値として、真偽を返却し真の新たの配列を返します。
var a = [1,5,10,15,20];
function bai(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  return element > 10;
}
b = a.filter(bai);
console.log(a);
console.log(b);
js_Array_filter.png

参考サイト:
MDN Array filter

[javascript ECMAScript5] Q. map()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
mapは配列の各要素にcallback関数を呼び出します。
callback関数の第一引数には値が入っており
callback関数内で値を加工して returnで返すと新しい配列が作成されます。
var a = [1,2,3];
function bai(element) {
  return element * 2;
}
b = a.map(bai);
console.log(a);
console.log(b);

js_Array_map.png

参考サイト:
MDN Array map

[javascript ECMAScript5] Q. forEach()

A.
ECMAScript5では、ビルトインArrayオブジェクトにメソッドが追加されました。
forEach(), map(), filter(), every(), some(), reduce(), reduceRight(), indexOf(), lastIndexOf()
が新たに追加されています。
FirefoxではJavaScript1.6で実装されました。
MDN Array で確認できます。

forEachは配列の各要素にcallback関数を呼び出します。
callback関数の第一引数は値、第二引数はインデックス、第三引数は元のArrayがそのまま入ってきます。
Arrayはリファレンスなので、callback関数内で値を変更すると元の配列の内容も変更されます。

var a = [1,5,15,20,25];
function log(element, index, array) {
  console.log("-----");
  console.log(element);
  console.log(index);
  array[index] = element * 5;
}
a.forEach(log);
console.log(a);
js_Array_forEach.png

参考サイト:
MDN forEach

[javascript] Q.ECMAScript5 isArray()

A. JavaScriptの配列は typeof では object が返ってくるので
Arrayか判断するのはちょいと面倒だったのですが
ECMAScript5では Array.isArray() というクラスメソッドが追加されました。

var a = [1, 2, 3];
var b = {x:1, y:2, z:3};

// typeof は object になる
console.log( typeof a );
console.log( typeof b );

// ECMAScript5では isArray が使える
console.log( Array.isArray(a) );
console.log( Array.isArray(b) );

// コンストラクタをみてみる
console.log( a.constructor );
console.log( b.constructor );
console.log( a.constructor === Array);
console.log( b.constructor === Array);

// ObjectのtoStringを呼び出して判断
console.log( Object.prototype.toString.call(a) );
console.log( Object.prototype.toString.call(b) );
console.log( Object.prototype.toString.call(a) === "[object Array]");
console.log( Object.prototype.toString.call(b) === "[object Array]");


js_isArray.png

参考サイト:
Chapter 3. Literals and Constructors

[javascript] Q.ECMAScript5 bind()

A.
ECMAScript5では、bind() というメソッドで関数のthisの値を変更できます。
var x = 1;
var y = 2;

// 1. bind
// 第一引数はthisの値を設定します。
function test1(y) {
  console.log( this );
  console.log( arguments );
  console.log( this.x + y );
}
test1(10); // 11
var a1 = { x:5 };
var b1 = test1.bind(a1);
b1(10); // 15

// 2. bind
// 第二引数以降は引数が順番にアサインされます
var goukei = function(x, y, z) {
  console.log( this );
  console.log( arguments );
  console.log( x + y + z);
}
goukei(1, 2, 3); // 6
var b2 = goukei.bind(null, 1, 2);
b2(3); // 6
var b3 = goukei.bind(null, 1, 2, 10);
b3(); // 13

js_bind_01.png

参考サイト:
MDN bind