どのようにJavaScript裸オブジェクトを作成しますか?


ヌードオブジェクトとは、naked objectとは、プロトタイプがないオブジェクトのことです.
JavaScriptは珍しい原型継承言語です.オブジェクトの属性を訪問する時は、まず自分の属性を見ます.own propertyとは、見つけられないなら、その原型の中を探して、見つけられないなら、この原型の原型を探し続けます.これはいわゆるプロトタイプチェーンを構成します.
プロトタイプ継承は独特な情報共有方式を提供していますが、面白い問題もあります.例えばwith構造
私は2011年のw 3 ctech広州での講演でwith構造の問題に触れましたので、stritモードでwithは禁止されました.
一つの問題は、with(obj)の場合、Objはあなたです.
コントロールできない対象は、コントロールできないリスクを導入します.コントロールできないということは、例えば、ブラウザオブジェクト(講演中に挙げたイベントオブジェクトのような)、または第三者ライブラリのオブジェクトまたは第三者ライブラリによって修正される可能性のあるオブジェクト(例えば、DOMオブジェクトのような、多くのライブラリが上に様々なものを追加する)です.
これは原型と何の関係がありますか?関係がありますwithはown propertyだけを検索するのではなく、プロトタイプチェーンまで遡ります.
例:
var name = 'hax'
with (console) {
  log('Hello ' + name)
}
なお、多くの実装において、コンサート・ソロ・ロゴのロゴ方法は、直接的にソロオブジェクトではなく、コンサートの原型上にある.
このようにしてプロトタイプのチェーンをたどるのはいいことのようですが、このコードを考えると:
var name = 'hax', count = 3
with (console) {
  for (var i = 0; i < count; i++)
    log('Hello ' + name)
}
このコードはいくつかの環境で走ることができます.しかし、Chromeではだめです.循環します.みんなはV 8エンジンを使っていますが、Chromeのsoneにはcount(count)の方法があります.
さらに嫌いなのは、ほぼすべての対象が原型を持っていて、Object.prototypeまでです.下記のコードを考慮します.
function constructor() {
  ...
}
with ({}) {
  var x = constructor() 
}
実際の結果はx=Object()に相当します.Object.prototype.com nstructor==Objectのためです.
これはまた、Object.prototypeを修正することによって、すべてのwithブロックを妨害する可能性がある.Object.prototypeはすべての対象の原型です.つまり、ほとんどの場合は
コントロールできない
【注意してください.確かにObject.prototypeをモデルとしない対象があります.例えば、いくつかの環境の中のhost対象がありますが、それらもあなたのコントロールできる対象ではないことは明らかです.】
withの最初の設計はミスがあります.own propertyだけを探すならいいです.しかし、今はもうこのような修正は不可能です.だから、他の方法しか考えられません.例えば、本当にnaked objectがあれば、対象を完全にコントロールすることができます.
聞くのは不可能です.nullとundefinedを除いて、すべての対象(number、stringとbootleanを含む)はObjectの例です.つまりObject.prototypeはプロトタイプチェーンの一番端としてあります.
しかし、ES 5が増加したObject.creat()方法はこのような能力を提供しています.Object.create(null)を呼び出すだけで裸のオブジェクトが得られます.これはいいです.したがって、私たちは比較的安全なwith方式を得ました.
with (Context({a: 1, b: 2})) {
  console.log(a, b)
}

function Context(obj) {
  var pds = {}
  var names = Object.getOwnPropertyNames(obj)
  for (var i = 0; i < names.length; i++) {
    pds[names[i]] = Object.getOwnPropertyDescriptor(obj, names[i])
  }
  return Object.create(null, pds)
}
しかし、古いのに対して、Object.creatメソッドがないブラウザはどうすればいいですか?
たくさんのブラウザがあります.プロト.属性は直接対象の___u uにアクセスできます.proto_だからNCZは裸対象に関する文章を書きました.
Naked JavaScript objectこの方法について言及する.見た目はObject.createよりも簡単です.
with({a: 1, b: 2, __proto__: null}) { ... }
まだ古いブラウザがありますが、サポートしていません.proto_,例えばIE.どうすればいいですか
実は方法があります
JavaScript対象の世界全体には、すべての対象に原型があるようですが、例外があります.
そうです.それはすべての対象の源です.Object.prototype.それは自分で原型がないのです.
var root = Object.prototype
Object.getPrototypeOf(root) === null // true
私たちはObject.prototypeの属性を全部deleteに落としたら、裸の対象を手に入れました.
でも、このようにObject.prototypeを破壊したら、私達のプログラムに影響があります.幸いにもiframeがあります.各iframeの実行環境は独立しています.そこで毎回iframeを作って、その中のObject.prototypeを持ってきて使います.(もったいないと聞こえますよね.
コードは以下の通りです
function nakedObject() {
	var iframe = document.createElement('iframe')
	iframe.width = iframe.height = 0
	iframe.style.display = 'none'
	document.appendChild(iframe)
	iframe.src = 'javascript:'
	var proto = iframe.contentWindow.Object.prototype
	iframe.parentNode.removeChild(iframe)
	iframe = null
	
	var props = [
		'constructor', 'hasOwnProperty', 'propertyIsEnumerable',
		'isPrototypeOf', 'toLocaleString', 'toString', 'valueOf' 
	]
	for (var i = 0; i < props.length; i++) {
		delete proto[props[i]]
	}
	return proto
}
しかし、この技術はかなり浪費されています.オブジェクトを作るためだけに、iframeとその環境を整えました.それは完全なホームページに相当します.IEの中で数千のこのような対象を創建して、何秒の時間と数十兆メモリを必要とします!この技術は本当に必要なところにしか使えません.例えばwithです.Object.creat(null)の行動をシミュレートするためにも同じですが、本当にこのような要求がありますか?もっと簡単な方法は普通の対象をObject.prototypeから継承した属性を隠すことです.これはwithには不向きですが、他の多くの場合には十分かもしれません.ですから、私もこのtrickをs 5-shimプロジェクトに提出するつもりはありません.自分のプロジェクトの一つだけを使うつもりです.
my.js
以上です.