読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

freeze/seal/preventExtensions の違いまとめ

ECMAScript 5 で追加された、Object.freezeやObject.sealを実行すると何ができなくなるのかについて。

こうなる。

preventExtensions seal freeze
プロパティの追加 × × ×
プロパティの削除 × ×
プロパティの値変更 ×
プロパティの属性変更 × ×

確認。

(function() { 
    //"use strict";
    // strict モードにすると、Firefox,Google Chrome,SafariではflozenObjectへの属性の追加等でもTypeErrorが発生するようになる。
    // IEでは、非strict モードと変わらない動作をする。
    
    describe('Flozen Object', function() {
       
        var flozenObject;
        
        beforeEach(function() {
            defineMatcher(this);
            
            flozenObject = createObject();
            Object.freeze( flozenObject );
        });
       
        it( 'should be fail to add property.', function() {
            flozenObject.x = "xxx";
            expect(flozenObject.x).toBeUndefined();
        });
       
        it( 'should be fail to delete property.', function() {
            delete flozenObject.a;
            expect(flozenObject.a).toEqual("aaa");
        });
       
        it( 'should be fail to modify property.', function() {
            flozenObject.a = "xxx" ;
            expect(flozenObject.a).toEqual("aaa");
        });
       
        it( 'should be fail to configure property.', function() {
            expect( function(){
                Object.defineProperty(flozenObject, "a", { 
                    enumerable : false
                });
            }).toThrowTypeError();
        });
       
    });
   
    describe('Sealed Object', function() {
        
        var sealedObject;
        
        beforeEach(function() {
            defineMatcher(this);
            
            sealedObject = createObject();
            Object.seal( sealedObject );
        });
        
        it( 'should be fail to add property.', function() {
            sealedObject.x = "xxx";
            expect(sealedObject.x).toBeUndefined();
        });
        
        it( 'should be fail to delete property.', function() {
            delete sealedObject.a;
            expect(sealedObject.a).toEqual("aaa");
        });
        
        it( 'should be success to modify property.', function() {
            sealedObject.a = "xxx" ;
            expect(sealedObject.a).toEqual("xxx");
        });
        
        it( 'should be fail to configure property.', function() {
            expect( function(){
                Object.defineProperty(sealedObject, "a", { 
                    enumerable : false
                });
            }).toThrowTypeError();
        });
        
    });
    
    describe('Non Extensible Object', function() {
        
        var nonExtensibleObject
        
        beforeEach(function() {
            defineMatcher(this);
            
            nonExtensibleObject = createObject();
            Object.preventExtensions( nonExtensibleObject );
        });
        
        it( 'should be fail to add property.', function() {
            nonExtensibleObject.x = "xxx";
            expect(nonExtensibleObject.x).toBeUndefined();
        });
        
        it( 'should be success to delete property.', function() {
            delete nonExtensibleObject.a;
            expect(nonExtensibleObject.a).toBeUndefined();
        });
        
        it( 'should be success to modify property.', function() {
            nonExtensibleObject.a = "xxx" ;
            expect(nonExtensibleObject.a).toEqual("xxx");
        });
        
        it( 'should be success to configure property.', function() {
            expect( function(){
                Object.defineProperty(nonExtensibleObject, "a", { 
                    enumerable : false
                });
            }).toSuccess();
        });
        
    });
    
    // utils
    function createObject() {
        return {
          a : "aaa"
        };
    }
    function defineMatcher( spec ) {
        spec.addMatchers( {
            toSuccess : function(){ 
                this.actual();
                return true;
            },
            toThrowTypeError : function(){
                try {
                    this.actual();
                    return false;
                } catch ( e ) {
                    return e.name === "TypeError";
                }
            }
        });
    }
    
}());

実行結果はこちら

  • strict モードにすると、Firefox,Google Chrome,SafariではfreezeされたObjectへの属性の追加等でもTypeErrorが発生するようになるので注意。
    • 非strictモードでは、「実行はできるが何も効果がない」という動作となる。
    • IE9では、モードに限らず同じ動作となる。