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では、モードに限らず同じ動作となる。