4

Firefox と Safari では、Object.isExtensible()が true で、通常のプロパティ割り当て (つまり、o.x = y) で新しいプロパティを追加できますが、 Object.defineProperty()「TypeError: Object.defineProperty(...) is not extensible」がスローされる状況が見られます。

これは型付き配列で発生していますが、おそらく他の型でも同様です。isExtensible()オブジェクトのプロパティを定義しようとしないことを確認するために使用しようとしています。

defineProperty を try/catch に入れることはできますが、ここで何が起こっているのかを理解したいと思います。何か案は?

jsfiddle の例を次に示します: http://jsfiddle.net/justinfagnani/qvgnk/

そしてコード:

function addProperty(o, name, value) {
  if (Object.isExtensible(o)) {
    Object.defineProperty(o, name, {'value': value});
    return true;
  }
  return false;
}

console.log(addProperty(new Date(), 'foo', 1));
console.log(addProperty(new ArrayBuffer(), 'foo', 1));

これは、呼び出しごとに少なくとも true または false を出力する必要があります。Firefox では、ArrayBuffer をスローします。

4

2 に答える 2

4

注: 型付き配列は現在、ES6/ES2015 仕様に含まれており、ArrayBuffers は実際に拡張可能です。この回答は、事前の参照用に提供されています。


型付き配列の仕様では、これについて明示的に何も述べていませんが、Web IDLを使用して作成されたオブジェクトを記述しており、次のように述べています。

特に指定しない限り、このセクションで定義されているオブジェクトの [[Extensible]] 内部プロパティの値はtrueです。

なぜ彼らがこれを仕様に入れたかはわかりませ[[Extensible]]んが、拡張可能でなくても trueにすることを選択した理由には次のものがあります。

  • 特定の関数/パスからの拡張を許可したい (false の場合は禁止)
  • ホスト オブジェクトの拡張を許可する可能性を残す (false から true への変更を禁止する)

ECMAScript 仕様(JavaScript の「標準」バージョン) によると、ホスト オブジェクトが変数の設定時にスローするかどうかは、実装に依存します ( §8.6.2 )。

特に指定がない限り、ホスト オブジェクトはこれらの内部メソッドを任意の方法で実装できます。たとえば、1 つの可能性[[Get]]として[[Put]]、特定のホスト オブジェクトの場合、実際にはプロパティ値を取得して保存しますが、[[HasProperty]]常に false が生成されます。ただし、ホスト オブジェクトの内部プロパティの指定された操作が実装でサポートされていない場合、その操作はTypeError試行時に例外をスローする必要があります。

この場合、仕様で指定された不変条件はどれも適用されないため、これは技術的に合法です。


明確にするための注意:[[Extensible]]が true の場合でも、ホスト オブジェクトの内部関数は、オブジェクトの拡張を許可する必要はありません。仕様は、ホスト オブジェクトが拡張されないことのみを義務付けています (参照[[Extensible]])が false の場合:

ホスト オブジェクトのinternal メソッドは、ホスト オブジェクトの内部プロパティが ECMAScript コードによって false であることが確認された[[DefineOwnProperty]]場合、そのホスト オブジェクトへの新しいプロパティの追加を許可してはなりません。[[Extensible]]

表 8/9 ( §8.6.2 ) の仕様で与えられた説明は、ネイティブ ECMAScript オブジェクトのみに関係し、ホスト オブジェクトには関係しないという点で、それ自体が誤解を招くものです。これらの表で説明されているように、プロパティを実装します。

于 2013-10-12T00:50:15.810 に答える
3

この動作は厳密モードと JavaScript エンジンに依存していると思います。

V8 (Chrome) では、厳密モードがオフの場合、は成功しますが、o.x = yには何も割り当てられませんが、厳密モードに関係なく常に例外がスローされます。o.xObject.defineProperty

厳密モードo.xでは、例外がスローされます。

RhinoObject.definePropertyでは例外がスローされ、o.x = y暗黙のうちに失敗します。

ここではいくつかの例を示します。

/usr/local/Cellar/tomcat6/6.0.37 >rhino -strict
Rhino 1.7 release 4 2012 06 18
js> var o = {a: 132};
js> Object.freeze(o);
[object Object]
js> Object.isExtensible(o);
false
js> o.x = 789;
789
js> o.x;
js> Object.defineProperty(o,'name',{value: 789})
js: uncaught JavaScript runtime exception: TypeError: Cannot add properties to this object because extensible is false.

V8で

/usr/local/Cellar/tomcat6/6.0.37 >node
> var o = {a: 123}
undefined
> Object.freeze(o)
{ a: 123 }   
> Object.isExtensible(o)
false
> o.x = 13
13
> o.x
undefined
> Object.defineProperty(o,'name',{value:123})
TypeError: Cannot define property:name, object is not extensible.
    at Function.defineProperty (native)
    at repl:1:9
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.EventEmitter.emit (events.js:98:17)

厳密モードで

/usr/local/Cellar/tomcat6/6.0.37 >node --use_strict
> var o = {a: 123};
undefined
> Object.freeze(o);
{ a: 123 }
> Object.isExtensible(o);
false
> o.x = 13
TypeError: Can't add property x, object is not extensible
    at repl:1:6
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.EventEmitter.emit (events.js:98:17)
    at emitKey (readline.js:1095:12)
于 2013-10-12T00:39:48.547 に答える