diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:40:17 -0500 |
commit | 33058f2b292b3a581333bdfb21b8f671898c5060 (patch) | |
tree | 51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/javascript/reference/global_objects/proxy | |
parent | 8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff) | |
download | translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2 translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip |
initial commit
Diffstat (limited to 'files/zh-cn/web/javascript/reference/global_objects/proxy')
17 files changed, 2642 insertions, 0 deletions
diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/apply/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/apply/index.html new file mode 100644 index 0000000000..62b8b67f5f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/apply/index.html @@ -0,0 +1,117 @@ +--- +title: handler.apply() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply +tags: + - ECMAScript6 + - JavaScript + - Method + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/apply +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.apply()</code></strong> 方法用于拦截函数的调用。</p> + +<div>{{EmbedInteractiveExample("pages/js/proxyhandler-apply.html", "taller")}}</div> + +<p class="hidden">此交互式示例的源代码存储在GitHub存储库中。 如果您想为交互式示例项目做出贡献,请克隆 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> 并向我们发起拉取请求</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + apply: function(target, thisArg, argumentsList) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>以下是传递给apply方法的参数,<code>this上下文绑定在</code>handler对象上.</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象(函数)。</dd> + <dt><code>thisArg</code></dt> + <dd>被调用时的上下文对象。</dd> + <dt><code>argumentsList</code></dt> + <dd>被调用时的参数数组。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>apply方法可以返回任何值。</code></p> + +<h2 id="描述">描述</h2> + +<p><strong><code>handler.apply</code></strong> 方法用于拦截函数的调用。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截目标对象的以下操作:</p> + +<ul> + <li><code>proxy(...args)</code></li> + <li>{{jsxref("Function.prototype.apply()")}} 和 {{jsxref("Function.prototype.call()")}}</li> + <li>{{jsxref("Reflect.apply()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违反了以下约束,代理将抛出一个TypeError:</p> + +<p><code>target</code>必须是可被调用的。也就是说,它必须是一个函数对象。</p> + +<h2 id="示例">示例</h2> + +<p>以下代码演示如何捕获函数的调用。</p> + +<pre class="brush: js">var p = new Proxy(function() {}, { + apply: function(target, thisArg, argumentsList) { + console.log('called: ' + argumentsList.join(', ')); + return argumentsList[0] + argumentsList[1] + argumentsList[2]; + } +}); + +console.log(p(1, 2, 3)); // "called: 1, 2, 3" + // 6 +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist', '[[Call]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist', '[[Call]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div class="hidden">此页面上的兼容性表格由结构化数据生成。 如果您想为数据做出贡献,请检出 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 并向我们发出拉取请求。</div> + +<p>{{Compat("javascript.builtins.Proxy.handler.apply")}}</p> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Function.prototype.apply")}}</li> + <li>{{jsxref("Function.prototype.call")}}</li> + <li>{{jsxref("Reflect.apply()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/construct/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/construct/index.html new file mode 100644 index 0000000000..209e9752e3 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/construct/index.html @@ -0,0 +1,130 @@ +--- +title: handler.construct() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/construct +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/construct +--- +<div>{{JSRef}}</div> + +<p><code><strong>handler.construct()</strong></code> 方法用于拦截{{jsxref("Operators/new", "new")}} 操作符. 为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有[[Construct]]内部方法(即 <code>new target</code> 必须是有效的)。</p> + +<p>{{EmbedInteractiveExample("pages/js/proxyhandler-construct.html", "taller")}}</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + construct: function(target, argumentsList, newTarget) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>下面的参数将会传递给<code>construct</code>方法,<code>this</code>绑定在handler上。</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> + <dt><code>argumentsList</code></dt> + <dd>constructor的参数列表。</dd> + <dt><code>newTarget</code></dt> + <dd>最初被调用的构造函数,就上面的例子而言是p。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>construct</code> 方法必须返回一个对象。</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.construct()</strong></code> 方法用于拦截 {{jsxref("Operators/new", "new")}}操作符。</p> + +<h3 id="拦截">拦截</h3> + +<p>该拦截器可以拦截以下操作:</p> + +<ul> + <li><code>new proxy(...args)</code></li> + <li>{{jsxref("Reflect.construct()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违反以下约定,代理将会抛出错误 {{jsxref("TypeError")}}:</p> + +<ul> + <li>必须返回一个对象.</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>下面代码演示如何拦截 {{jsxref("Operators/new", "new")}} 操作。</p> + +<pre class="brush: js">var p = new Proxy(function() {}, { + construct: function(target, argumentsList, newTarget) { + console.log('called: ' + argumentsList.join(', ')); + return { value: argumentsList[0] * 10 }; + } +}); + +console.log(new p(1).value); // "called: 1" + // 10 +</pre> + +<p>下面的代码违反了约定.</p> + +<pre class="brush: js">var p = new Proxy(function() {}, { + construct: function(target, argumentsList, newTarget) { + return 1; + } +}); + +new p(); // TypeError is thrown +</pre> + +<p>下面的代码未能正确的初始化Proxy。Proxy初始化时,传给它的<code>target</code> 必须具有一个有效的constructor供<code>new</code>操作符调用。</p> + +<pre class="brush: js">var p = new Proxy({}, { + construct: function(target, argumentsList, newTarget) { + return {}; + } +}); + +new p(); // TypeError is thrown, "p" is not a constructor +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget', '[[Construct]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget', '[[Construct]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{Compat("javascript.builtins.Proxy.handler.construct")}}</div> + +<div id="compat-mobile"> </div> + +<h2 id="相关主题">相关主题</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Operators/new", "new")}} operator.</li> + <li>{{jsxref("Reflect.construct()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/defineproperty/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/defineproperty/index.html new file mode 100644 index 0000000000..9912e043a0 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/defineproperty/index.html @@ -0,0 +1,181 @@ +--- +title: handler.defineProperty() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/defineProperty +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/defineProperty +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.defineProperty()</code></strong> 用于拦截对对象的 {{jsxref("Object.defineProperty()")}} 操作。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + defineProperty: function(target, property, descriptor) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>下列参数将会被传递给 <code>defineProperty</code> 方法。<code> this</code> 绑定在 handler 对象上。</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> + <dt><code>property</code></dt> + <dd>待检索其描述的属性名。</dd> + <dt><code>descriptor</code></dt> + <dd>待定义或修改的属性的描述符。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>defineProperty</code> 方法必须以一个 {{jsxref("Boolean")}} 返回,表示定义该属性的操作成功与否。</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.defineProperty()</strong></code> 用于拦截对对象的 {{jsxref("Object.defineProperty()")}} 操作。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截目标对象的以下操作 :</p> + +<ul> + <li>{{jsxref("Object.defineProperty()")}}</li> + <li>{{jsxref("Reflect.defineProperty()")}}</li> + <li>{{jsxref("proxy.property='value'")}}</li> +</ul> + +<h3 id="不变量">不变量</h3> + +<p>如果违背了以下的不变量,proxy会抛出 {{jsxref("TypeError")}}:</p> + +<ul> + <li>如果目标对象不可扩展, 将不能添加属性。</li> + <li>不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话。</li> + <li>如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的。</li> + <li>如果一个属性在目标对象中存在对应的属性,那么 <code>Object.defineProperty(target, prop, descriptor)</code> 将不会抛出异常。</li> + <li>在严格模式下, <code>false</code> 作为<code> handler.defineProperty</code> 方法的返回值的话将会抛出 {{jsxref("TypeError")}} 异常.</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示如何拦截对目标对象的 {{jsxref("Object.defineProperty()")}} 操作。</p> + +<pre class="brush: js">var p = new Proxy({}, { + defineProperty: function(target, prop, descriptor) { + console.log('called: ' + prop); + return true; + } +}); + +var desc = { configurable: true, enumerable: true, value: 10 }; +Object.defineProperty(p, 'a', desc); // "called: a" +</pre> + +<p>当调用 {{jsxref("Object.defineProperty()")}} 或者 {{jsxref("Reflect.defineProperty()")}},传递给 <code>defineProperty</code> 的 <code>descriptor</code> 有一个限制 - 只有以下属性才有用,非标准的属性将会被无视 :</p> + +<ul> + <li><code>enumerable</code></li> + <li><code>configurable</code></li> + <li><code>writable</code></li> + <li><code>value</code></li> + <li><code>get</code></li> + <li><code>set</code></li> +</ul> + +<pre class="brush: js">var p = new Proxy({}, { + defineProperty(target, prop, descriptor) { + console.log(descriptor); + return Reflect.defineProperty(target, prop, descriptor); + } +}); + +Object.defineProperty(p, 'name', { + value: 'proxy', + type: 'custom' +}); // { value: 'proxy' } +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc', '[[DefineOwnProperty]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc', '[[DefineOwnProperty]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.defineProperty()")}}</li> + <li>{{jsxref("Reflect.defineProperty()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/deleteproperty/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/deleteproperty/index.html new file mode 100644 index 0000000000..6cb4255755 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/deleteproperty/index.html @@ -0,0 +1,149 @@ +--- +title: handler.deleteProperty() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/deleteProperty +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/deleteProperty +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.deleteProperty()</code></strong> 方法用于拦截对对象属性的 {{jsxref("Operators/delete", "delete")}} 操作。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + deleteProperty: function(target, property) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p><code>deleteProperty</code> 方法将会接受以下参数。 <code>this</code> 被绑定在 handler上。</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> + <dt><code>property</code></dt> + <dd>待删除的属性名。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>deleteProperty</code> 必须返回一个 {{jsxref("Boolean")}} 类型的值,表示了该属性是否被成功删除。</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.deleteProperty()</strong></code> 方法可以拦截 {{jsxref("Operators/delete", "delete")}} 操作。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截以下操作:</p> + +<ul> + <li>删除属性: <code>delete proxy[foo]</code> 和 <code>delete proxy.foo</code></li> + <li>{{jsxref("Reflect.deleteProperty()")}}</li> +</ul> + +<h3 id="不变量">不变量</h3> + +<p>如果违背了以下不变量,proxy 将会抛出一个 {{jsxref("TypeError")}}:</p> + +<ul> + <li>如果目标对象的属性是不可配置的,那么该属性不能被删除。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示了对 {{jsxref("Operators/delete", "delete")}} 操作的拦截。</p> + +<pre class="brush: js">var p = new Proxy({}, { + deleteProperty: function(target, prop) { + console.log('called: ' + prop); + return true; + } +}); + +delete p.a; // "called: a" +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-delete-p', '[[Delete]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-delete-p', '[[Delete]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Operators/delete", "delete")}} 操作符</li> + <li>{{jsxref("Reflect.deleteProperty()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/get/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/get/index.html new file mode 100644 index 0000000000..14a350436a --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/get/index.html @@ -0,0 +1,177 @@ +--- +title: handler.get() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/get +tags: + - ECMAScript6 + - JavaScript + - Method + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/get +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.get()</code></strong> 方法用于拦截对象的读取属性操作。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + get: function(target, property, receiver) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>以下是传递给get方法的参数,<code>this上下文绑定在</code>handler对象上.</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> + <dt><code>property</code></dt> + <dd>被获取的属性名。</dd> + <dt><code>receiver</code></dt> + <dd>Proxy或者继承Proxy的对象</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>get方法可以返回任何值。</p> + +<h2 id="描述">描述</h2> + +<p><strong><code>handler.get</code></strong> 方法用于拦截对象的读取属性操作。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截目标对象的以下操作:</p> + +<ul> + <li>访问属性: <code>proxy[foo]和</code> <code>proxy.bar</code></li> + <li>访问原型链上的属性: <code>Object.create(proxy)[foo]</code></li> + <li>{{jsxref("Reflect.get()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违背了以下的约束,proxy会抛出 {{jsxref("TypeError")}}:</p> + +<ul> + <li>如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同。</li> + <li>如果要访问的目标属性没有配置访问方法,即get方法是undefined的,则返回值必须为undefined。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示如何拦截属性值的读取操作。</p> + +<pre class="brush: js">var p = new Proxy({}, { + get: function(target, prop, receiver) { + console.log("called: " + prop); + return 10; + } +}); + +console.log(p.a); // "called: a" + // 10 +</pre> + +<p>以下代码演示违反约束的情况。</p> + +<pre class="brush: js">var obj = {}; +Object.defineProperty(obj, "a", { + configurable: false, + enumerable: false, + value: 10, + writable: false +}); + +var p = new Proxy(obj, { + get: function(target, prop) { + return 20; + } +}); + +p.a; //会抛出TypeError +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver', '[[Get]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver', '[[Get]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Reflect.get()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getownpropertydescriptor/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getownpropertydescriptor/index.html new file mode 100644 index 0000000000..470b2c6ad9 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getownpropertydescriptor/index.html @@ -0,0 +1,168 @@ +--- +title: handler.getOwnPropertyDescriptor() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.getOwnPropertyDescriptor()</code></strong> 方法是 {{jsxref("Object.getOwnPropertyDescriptor()")}} 的钩子。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + getOwnPropertyDescriptor: function(target, prop) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p><code>下列参数会被传入 getOwnPropertyDescriptor</code> 方法中。这是绑定到handler上。 </p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> + <dt><code>prop</code></dt> + <dd>返回属性名称的描述。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>getOwnPropertyDescriptor</code> 方法必须返回一个 object 或 <code>undefined</code>。</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.getOwnPropertyDescriptor()</strong></code> 方法是 {{jsxref("Object.getOwnPropertyDescriptor()")}} 的陷阱。</p> + +<h3 id="拦截">拦截</h3> + +<p>这个陷阱可以拦截这些操作:</p> + +<ul> + <li>{{jsxref("Object.getOwnPropertyDescriptor()")}}</li> + <li>{{jsxref("Reflect.getOwnPropertyDescriptor()")}}</li> +</ul> + +<h3 id="不变量">不变量</h3> + +<p>如果下列不变量被违反,代理将抛出一个 {{jsxref("TypeError")}}:</p> + +<ul> + <li><code>getOwnPropertyDescriptor</code> 必须返回一个 object 或 <code>undefined</code>。</li> + <li>如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在。</li> + <li>如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在。</li> + <li>如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在。</li> + <li>属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在。</li> + <li>Object.getOwnPropertyDescriptor(target)的结果可以使用 Object.defineProperty 应用于目标对象,也不会抛出异常。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下是 {{jsxref("Object.getOwnPropertyDescriptor()")}} 的代码陷阱:</p> + +<pre class="brush: js">var p = new Proxy({ a: 20}, { + getOwnPropertyDescriptor: function(target, prop) { + console.log('called: ' + prop); + return { configurable: true, enumerable: true, value: 10 }; + } +}); + +console.log(Object.getOwnPropertyDescriptor(p, 'a').value); // "called: a" + // 10 +</pre> + +<p>以下代码则违反了不变量。</p> + +<pre class="brush: js">var obj = { a: 10 }; +Object.preventExtensions(obj); +var p = new Proxy(obj, { + getOwnPropertyDescriptor: function(target, prop) { + return undefined; + } +}); + +Object.getOwnPropertyDescriptor(p, 'a'); // TypeError is thrown +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p', '[[GetOwnProperty]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p', '[[GetOwnProperty]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.getOwnPropertyDescriptor()")}}</li> + <li>{{jsxref("Reflect.getOwnPropertyDescriptor()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getprototypeof/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getprototypeof/index.html new file mode 100644 index 0000000000..215d2d9646 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/getprototypeof/index.html @@ -0,0 +1,141 @@ +--- +title: handler.getPrototypeOf() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/getPrototypeOf +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Proxy + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/getPrototypeOf +--- +<div>{{JSRef("Global_Objects", "Proxy")}}</div> + +<p><strong><code>handler.getPrototypeOf()</code></strong> 是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。</p> + +<div>{{EmbedInteractiveExample("pages/js/proxyhandler-getprototypeof.html", "taller")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="brush: js">const <var>p</var> = new Proxy(<var>obj</var>, { + getPrototypeOf(<var>target</var>) { + ... + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>当 <code>getPrototypeOf</code> 方法被调用时,<code>this</code> 指向的是它所属的处理器对象。</p> + +<dl> + <dt><code>target</code></dt> + <dd>被代理的目标对象。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>getPrototypeOf</code> 方法的返回值必须是一个对象或者 <code>null</code>。</p> + +<h2 id="描述">描述</h2> + +<p>在 JavaScript 中,下面这五种操作(方法/属性/运算符)可以触发 JS 引擎读取一个对象的原型,也就是可以触发 <code>getPrototypeOf()</code> 代理方法的运行:</p> + +<ul> + <li>{{jsxref("Object.getPrototypeOf()")}}</li> + <li>{{jsxref("Reflect.getPrototypeOf()")}}</li> + <li>{{jsxref("Object/proto", "__proto__")}}</li> + <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> + <li>{{jsxref("Operators/instanceof", "instanceof")}}</li> +</ul> + +<p>如果遇到了下面两种情况,JS 引擎会抛出 {{jsxref("TypeError")}} 异常:</p> + +<ul> + <li><code>getPrototypeOf()</code> 方法返回的不是对象也不是 <code>null。</code></li> + <li>目标对象是不可扩展的,且 <code>getPrototypeOf()</code> 方法返回的原型不是目标对象本身的原型。</li> +</ul> + +<h2 id="示例">示例</h2> + +<h3 id="基本用法">基本用法</h3> + +<pre class="brush: js">var obj = {}; +var proto = {}; +var handler = { + getPrototypeOf(target) { + console.log(target === obj); // true + console.log(this === handler); // true + return proto; + } +}; + +var p = new Proxy(obj, handler); +console.log(Object.getPrototypeOf(p) === proto); // true +</pre> + +<h3 id="5_种触发_getPrototypeOf_代理方法的方式">5 种触发 getPrototypeOf 代理方法的方式</h3> + +<pre class="brush: js">var obj = {}; +var p = new Proxy(obj, { + getPrototypeOf(target) { + return Array.prototype; + } +}); +console.log( + Object.getPrototypeOf(p) === Array.prototype, // true + Reflect.getPrototypeOf(p) === Array.prototype, // true + p.__proto__ === Array.prototype, // true + Array.prototype.isPrototypeOf(p), // true + p instanceof Array // true +); +</pre> + +<h3 id="两种情况下的异常">两种情况下的异常</h3> + +<pre class="brush: js">var obj = {}; +var p = new Proxy(obj, { + getPrototypeOf(target) { + return "foo"; + } +}); +Object.getPrototypeOf(p); // TypeError: "foo" is not an object or null + +var obj = Object.preventExtensions({}); +var p = new Proxy(obj, { + getPrototypeOf(target) { + return {}; + } +}); +Object.getPrototypeOf(p); // TypeError: expected same prototype value +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof', '[[GetPrototypeOf]]')}}</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Proxy.handler.getPrototypeOf")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.getPrototypeOf()")}}</li> + <li>{{jsxref("Reflect.getPrototypeOf()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/has/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/has/index.html new file mode 100644 index 0000000000..fead0846ff --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/has/index.html @@ -0,0 +1,176 @@ +--- +title: handler.has() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/has +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/has +--- +<div>{{JSRef}}</div> + +<p> <strong><code>handler.has()</code></strong> 方法是针对 {{jsxref("Operators/in", "in")}} 操作符的代理方法。</p> + + + + + +<p>{{EmbedInteractiveExample("pages/js/proxyhandler-has.html", "taller")}}</p> + + + + + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + has: function(target, prop) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p><code>下面是传递给 has</code> 方法的参数. <code>this</code> is bound to the handler.</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象.</dd> + <dt><code>prop</code></dt> + <dd>需要检查是否存在的属性.</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>has</code> 方法返回一个 boolean 属性的值.</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.has</strong></code> 方法可以看作是针对 {{jsxref("Operators/in", "in")}} 操作的钩子.</p> + +<h3 id="拦截">拦截</h3> + +<p>这个钩子可以拦截下面这些操作:</p> + +<ul> + <li>属性查询: <code>foo in proxy</code></li> + <li>继承属性查询: <code>foo in Object.create(proxy)</code></li> + <li><code>with</code> 检查<code>: with(proxy) { (foo); }</code></li> + <li>{{jsxref("Reflect.has()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违反了下面这些规则, proxy 将会抛出 {{jsxref("TypeError")}}:</p> + +<ul> + <li>如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏.</li> + <li>如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>下面的代码拦截了 {{jsxref("Operators/in", "in")}} 操作符.</p> + +<pre class="brush: js">var p = new Proxy({}, { + has: function(target, prop) { + console.log('called: ' + prop); + return true; + } +}); + +console.log('a' in p); // "called: a" + // true +</pre> + +<p>下面的代码违反了约束.</p> + +<pre class="brush: js">var obj = { a: 10 }; +Object.preventExtensions(obj); +var p = new Proxy(obj, { + has: function(target, prop) { + return false; + } +}); + +'a' in p; // TypeError is thrown +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p', '[[HasProperty]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p', '[[HasProperty]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器支持">浏览器支持</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="其他">其他</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Operators/in", "in")}} operator</li> + <li>{{jsxref("Reflect.has()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/index.html new file mode 100644 index 0000000000..7cbefe2838 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/index.html @@ -0,0 +1,76 @@ +--- +title: Proxy handler +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler +tags: + - ECMAScript 2015 + - JavaScript + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy +--- +<div>{{JSRef}}</div> + +<div>Proxy 的 handler 对象是一个占位符对象,它包含了用于 {{jsxref("Proxy")}} 的陷阱(Trap)函数。</div> + +<div>此处可以理解为由Proxy所暴露出的钩子函数,handler作为挂载钩子函数的对象存在,不同的操作会触发不同的钩子函数</div> + +<div>,handler提供了覆写钩子函数的方法。</div> + +<h2 id="方法">方法</h2> + +<p>所有的陷阱是可选的。如果某个陷阱没有定义,那么就会保留默认行为。</p> + +<dl> + <dt>{{jsxref("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}</dt> + <dd>在读取代理对象的原型时触发该操作,比如在执行 <code>{{jsxref("Object.getPrototypeOf")}}(proxy)</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}</dt> + <dd>在设置代理对象的原型时触发该操作,比如在执行 <code>{{jsxref("Object.setPrototypeOf")}}(proxy, null)</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}}</dt> + <dd>在判断一个代理对象是否是可扩展时触发该操作,比如在执行 <code>{{jsxref("Object.isExtensible")}}(proxy)</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}}</dt> + <dd>在让一个代理对象不可扩展时触发该操作,比如在执行 <code>{{jsxref("Object.preventExtensions")}}(proxy)</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}</dt> + <dd>在获取代理对象某个属性的属性描述时触发该操作,比如在执行 <code>{{jsxref("Object.getOwnPropertyDescriptor")}}(proxy, "foo")</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}}</dt> + <dd>在定义代理对象某个属性时的属性描述时触发该操作,比如在执行 <code>{{jsxref("Object.defineProperty")}}(proxy, "foo", {})</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/has", "handler.has()")}}</dt> + <dd>在判断代理对象是否拥有某个属性时触发该操作,比如在执行 <code>"foo" {{jsxref("Operators/in", "in")}} proxy</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}}</dt> + <dd>在读取代理对象的某个属性时触发该操作,比如在执行 <code>proxy.foo</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}}</dt> + <dd>在给代理对象的某个属性赋值时触发该操作,比如在执行 <code>proxy.foo = 1</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}}</dt> + <dd>在删除代理对象的某个属性时触发该操作,即使用 {{jsxref("Operators/delete", "delete")}} 运算符,比如在执行 <code>delete proxy.foo</code> 时。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}}</dt> + <dd>{{jsxref("Object.getOwnPropertyNames")}} 和{{jsxref("Object.getOwnPropertySymbols")}} 的陷阱。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/apply", "handler.apply()")}}</dt> + <dd>函数调用操作的陷阱。</dd> + <dt>{{jsxref("Global_Objects/Proxy/handler/construct", "handler.construct()")}}</dt> + <dd>{{jsxref("Operators/new", "new")}} 运算符的陷阱。</dd> +</dl> + +<p>一些不标准的陷阱已经<a href="/zh-CN/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#Proxy">废弃并且被移除了</a></p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots', 'Proxy Object Internal Methods and Internal Slots')}}</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Proxy.handler")}}</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{JSxRef("Proxy")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/isextensible/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/isextensible/index.html new file mode 100644 index 0000000000..7be418197f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/isextensible/index.html @@ -0,0 +1,123 @@ +--- +title: handler.isExtensible() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/isExtensible +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/isExtensible +--- +<div>{{JSRef}}<br> +<strong>handler.isExtensible() </strong>方法用于拦截对对象的Object.isExtensible()。</div> + +<div> +<p>{{EmbedInteractiveExample("pages/js/proxyhandler-isextensible.html", "taller")}}</p> +</div> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + isExtensible: function(target) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>下列参数将会被传递给 <code>isExtensible</code>方法。 this 绑定在 handler 对象上。</p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>isExtensible</code>方法必须返回一个 Boolean值或可转换成Boolean的值。</p> + +<h2 id="描述">描述</h2> + +<p>handler.isExtensible()用于拦截对对象的Object.isExtensible()。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截目标对象的以下操作:</p> + +<ul> + <li>{{jsxref("Object.isExtensible()")}}</li> + <li>{{jsxref("Reflect.isExtensible()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违背了以下的约束,proxy会抛出 TypeError:</p> + +<ul> + <li><code>Object.isExtensible(proxy)</code> 必须同<code>Object.isExtensible(target)</code>返回相同值。也就是必须返回true或者为true的值,返回false和为false的值都会报错。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示{{jsxref("Object.isExtensible()")}}.</p> + +<pre class="brush: js">var p = new Proxy({}, { + isExtensible: function(target) { + console.log('called'); + return true;//也可以return 1;等表示为true的值 + } +}); + +console.log(Object.isExtensible(p)); // "called" + // true +</pre> + +<p>以下代码演示违反约束的情况。</p> + +<pre class="brush: js">var p = new Proxy({}, { + isExtensible: function(target) { + return false;//return 0;return NaN等都会报错 + } +}); + +Object.isExtensible(p); // TypeError is thrown +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-isextensible', '[[IsExtensible]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-isextensible', '[[IsExtensible]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Proxy.handler.isExtensible")}}</p> +</div> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.isExtensible()")}}</li> + <li>{{jsxref("Reflect.isExtensible()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/ownkeys/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/ownkeys/index.html new file mode 100644 index 0000000000..956b908375 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/ownkeys/index.html @@ -0,0 +1,193 @@ +--- +title: handler.ownKeys() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/ownKeys +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/ownKeys +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.ownKeys()</code></strong> 方法用于拦截 {{jsxref("Reflect.ownKeys()")}}.</p> + + + +<p>{{EmbedInteractiveExample("pages/js/proxyhandler-ownkeys.html", "taller")}}</p> + + + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + ownKeys: function(target) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>下面的参数被传递给<code>ownKeys。this</code>被绑定在<code>handler上。</code></p> + +<dl> + <dt><code>target</code></dt> + <dd>目标对象.</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>ownKeys</code> 方法必须返回一个可枚举对象.</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.ownKeys()</strong></code> 方法用于拦截 {{jsxref("Reflect.ownKeys()")}}.</p> + +<h3 id="拦截">拦截</h3> + +<p>该拦截器可以拦截以下操作::</p> + +<ul> + <li>{{jsxref("Object.getOwnPropertyNames()")}}</li> + <li>{{jsxref("Object.getOwnPropertySymbols()")}}</li> + <li>{{jsxref("Object.keys()")}}</li> + <li>{{jsxref("Reflect.ownKeys()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违反了下面的约束,proxy将抛出错误 {{jsxref("TypeError")}}:</p> + +<ul> + <li><code>ownKeys</code> 的结果必须是一个数组.</li> + <li>数组的元素类型要么是一个 {{jsxref("String")}} ,要么是一个 {{jsxref("Symbol")}}.</li> + <li>结果列表必须包含目标对象的所有不可配置(non-configurable )、自有(own)属性的key.</li> + <li>如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的key,不能有其它值.</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>下面的代码拦截 {{jsxref("Object.getOwnPropertyNames()")}}.</p> + +<pre class="brush: js">var p = new Proxy({}, { + ownKeys: function(target) { + console.log('called'); + return ['a', 'b', 'c']; + } +}); + +console.log(Object.getOwnPropertyNames(p)); // "called" + // [ 'a', 'b', 'c' ]</pre> + +<p>下面的代码违反了约定</p> + +<pre class="brush: js example-bad">var obj = {}; +Object.defineProperty(obj, 'a', { + configurable: false, + enumerable: true, + value: 10 } +); + +var p = new Proxy(obj, { + ownKeys: function(target) { + return [123, 12.5, true, false, undefined, null, {}, []]; + } +}); + +console.log(Object.getOwnPropertyNames(p)); + +// TypeError: proxy [[OwnPropertyKeys]] 必须返回一个数组 +// 数组元素类型只能是String或Symbol +</pre> + +<h2 id="标准">标准</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys', '[[OwnPropertyKeys]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys', '[[OwnPropertyKeys]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容">浏览器兼容</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoDesktop("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("18")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="兼容性注意事项">兼容性注意事项</h2> + +<h3 id="Firefox火狐">Firefox火狐</h3> + +<ul> + <li>在Gecko 42 {{geckoRelease(42)}}版本中, <code>ownKey</code> 的实施已经更新了,为了反映最终的ES5标准 (see {{bug(1049662)}}): + + <ul> + <li>现在需要检查结果是不是数组以及数组元素类型是不是string或symbol.</li> + <li>枚举重复的自有的属性名称不再失败.</li> + </ul> + </li> +</ul> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.getOwnPropertyNames()")}}</li> + <li>{{jsxref("Reflect.ownKeys()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/preventextensions/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/preventextensions/index.html new file mode 100644 index 0000000000..dd6823c9dd --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/preventextensions/index.html @@ -0,0 +1,120 @@ +--- +title: handler.preventExtensions() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/preventExtensions +tags: + - Proxy 代理 拦截 +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/preventExtensions +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.preventExtensions()</code></strong> 方法用于设置对{{jsxref("Object.preventExtensions()")}}的拦截</p> + +<p>{{EmbedInteractiveExample("pages/js/proxyhandler-preventextensions.html", "taller")}}</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js notranslate">var p = new Proxy(target, { + preventExtensions: function(target) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>以下参数传递给 <code>preventExtensions</code> 方法. 它会绑定到这个handler.</p> + +<dl> + <dt><code>target</code></dt> + <dd>所要拦截的目标对象.</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>preventExtensions</code> 方法返回一个布尔值.</p> + +<h2 id="描述">描述</h2> + +<p><code><strong>handler.preventExtensions()</strong></code> 拦截 {{jsxref("Object.preventExtensions()")}}返回一个布尔值.</p> + +<h3 id="拦截">拦截</h3> + +<p>这个trap可以拦截这些操作:</p> + +<ul> + <li>{{jsxref("Object.preventExtensions()")}}</li> + <li>{{jsxref("Reflect.preventExtensions()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违反了下列规则, proxy则会抛出一个 {{jsxref("TypeError")}}:</p> + +<ul> + <li>如果目标对象是可扩展的,那么只能返回 <code>false</code></li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示了如何拦截{{jsxref("Object.preventExtensions()")}}。</p> + +<pre class="brush: js notranslate">var p = new Proxy({}, { + preventExtensions: function(target) { + console.log('called'); + Object.preventExtensions(target); + return true; + } +}); + +console.log(Object.preventExtensions(p)); // "called" + // false +</pre> + +<p>以下代码违反了约束.</p> + +<pre class="brush: js notranslate">var p = new Proxy({}, { + preventExtensions: function(target) { + return true; + } +}); + +Object.preventExtensions(p); // 抛出类型错误 +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-preventextensions', '[[PreventExtensions]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-preventextensions', '[[PreventExtensions]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Proxy.handler.preventExtensions")}}</p> +</div> + +<h2 id="参考">参考</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.preventExtensions()")}}</li> + <li>{{jsxref("Reflect.preventExtensions()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/set/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/set/index.html new file mode 100644 index 0000000000..c66481647a --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/set/index.html @@ -0,0 +1,125 @@ +--- +title: handler.set() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/set +tags: + - ECMAScript6 + - JavaScript + - Method + - Proxy + - Proxy拦截 +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/set +--- +<div>{{JSRef}}</div> + +<p><code><strong>handler.set()</strong></code> 方法是设置属性值操作的捕获器。</p> + +<div>{{EmbedInteractiveExample("pages/js/proxyhandler-set.html", "taller")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox">const <var>p</var> = new Proxy(<var>target</var>, { + set: function(<var>target</var>, <var>property</var>, <var>value</var>, <var>receiver</var>) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>以下是传递给 <code>set()</code> 方法的参数。<code>this</code> 绑定在 handler 对象上。</p> + +<dl> + <dt><code><var>target</var></code></dt> + <dd>目标对象。</dd> + <dt><code><var>property</var></code></dt> + <dd>将被设置的属性名或 {{jsxref("Symbol")}}。</dd> + <dt><code><var>value</var></code></dt> + <dd>新属性值。</dd> + <dt><code><var>receiver</var></code></dt> + <dd>最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。 + <div class="note"> + <p><strong>比如:</strong>假设有一段代码执行 <code>obj.name = "jen"</code>, <code><var>obj</var></code> 不是一个 proxy,且自身不含 <code>name</code> 属性,但是它的原型链上有一个 proxy,那么,那个 proxy 的 <code>set()</code> 处理器会被调用,而此时,<code><var>obj</var></code> 会作为 receiver 参数传进来。</p> + </div> + </dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p><code>set()</code> 方法应当返回一个布尔值。</p> + +<ul> + <li>返回 <code>true</code> 代表属性设置成功。</li> + <li>在严格模式下,如果 <code>set()</code> 方法返回 <code>false</code>,那么会抛出一个 {{jsxref("TypeError")}} 异常。</li> +</ul> + +<h2 id="描述">描述</h2> + +<p><code>handler.set()</code> 方法用于拦截设置属性值的操作。</p> + +<h3 id="拦截">拦截</h3> + +<p>该方法会拦截目标对象的以下操作:</p> + +<ul> + <li>指定属性值:<code>proxy[foo] = bar</code> 和 <code>proxy.foo = bar</code></li> + <li>指定继承者的属性值:<code>Object.create(proxy)[foo] = bar</code></li> + <li>{{jsxref("Reflect.set()")}}</li> +</ul> + +<h3 id="约束">约束</h3> + +<p>如果违背以下的约束条件,proxy 会抛出一个 {{jsxref("TypeError")}} 异常:</p> + +<ul> + <li>若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值。</li> + <li>如果目标属性没有配置存储方法,即 <code>[[Set]]</code> 属性的是 <code>undefined</code>,则不能设置它的值。</li> + <li>在严格模式下,如果 <code>set()</code> 方法返回 <code>false</code>,那么也会抛出一个 {{jsxref("TypeError")}} 异常。</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>以下代码演示如何捕获属性的设置操作。</p> + +<pre class="brush: js">var p = new Proxy({}, { + set: function(target, prop, value, receiver) { + target[prop] = value; + console.log('property set: ' + prop + ' = ' + value); + return true; + } +}) + +console.log('a' in p); // false + +p.a = 10; // "property set: a = 10" +console.log('a' in p); // true +console.log(p.a); // 10</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">规范</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver', '[[Set]]')}}</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Proxy.handler.set")}}</p> + +<h2 id="另见">另见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Reflect.set()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/setprototypeof/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/setprototypeof/index.html new file mode 100644 index 0000000000..9d88cd2593 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/handler/setprototypeof/index.html @@ -0,0 +1,124 @@ +--- +title: handler.setPrototypeOf() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/handler/setPrototypeOf +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy/setPrototypeOf +--- +<div>{{JSRef}}</div> + +<p><strong><code>handler.setPrototypeOf()</code></strong> 方法主要用来拦截 {{jsxref("Object.setPrototypeOf()")}}.</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js">var p = new Proxy(target, { + setPrototypeOf: function(target, prototype) { + } +}); +</pre> + +<h3 id="参数">参数</h3> + +<p>以下参数传递给 <code>setPrototypeOf</code> 方法. </p> + +<dl> + <dt><code>target</code></dt> + <dd>被拦截目标对象.</dd> + <dt><code>prototype</code></dt> + <dd>对象新原型或为<code>null</code>.</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>如果成功修改了<code>[[Prototype]]</code>, <code>setPrototypeOf</code> 方法返回 <code>true</code>,否则返回 <code>false</code>.</p> + +<h2 id="描述">描述</h2> + +<p>这个 <code><strong>handler.setPrototypeOf</strong></code> 方法用于拦截 {{jsxref("Object.setPrototypeOf()")}}.</p> + +<h3 id="拦截">拦截</h3> + +<p>这个方法可以拦截以下操作:</p> + +<ul> + <li>{{jsxref("Object.setPrototypeOf()")}}</li> + <li>{{jsxref("Reflect.setPrototypeOf()")}}</li> +</ul> + +<h3 id="Invariants">Invariants</h3> + +<p>如果违反了下列规则,则proxy将抛出一个{{jsxref("TypeError")}}:</p> + +<ul> + <li><code><font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">如果 </span></font>target</code> 不可扩展, 原型参数必须与<code>Object.getPrototypeOf(target)</code> 的值相同.</li> +</ul> + +<h2 id="示例">示例</h2> + +<p>如果你不想为你的对象设置一个新的原型,你的handler's的<code>setPrototypeOf</code>方法可以返回false,也可以抛出异常。</p> + +<p>The former approach means that any operation that performs such mutation, that throws an exception on failure to mutate, will have to create the exception itself. For example, {{jsxref("Object.setPrototypeOf()")}} will create and throw a <code>TypeError</code> itself. If the mutation is performed by an operation that <em>doesn't</em> ordinarily throw in case of failure, such as {{jsxref("Reflect.setPrototypeOf()")}}, no exception will be thrown.</p> + +<pre class="brush: js">var handlerReturnsFalse = { + setPrototypeOf(target, newProto) { + return false; + } +}; + +var newProto = {}, target = {}; + +var p1 = new Proxy(target, handlerReturnsFalse); +Object.setPrototypeOf(p1, newProto); // throws a TypeError +Reflect.setPrototypeOf(p1, newProto); // returns false +</pre> + +<p>The latter approach will cause <em>any</em> operation that attempts to mutate, to throw. This approach is required if you want even non-throwing operations to throw on failure, or you want to throw a custom exception value.</p> + +<pre class="brush: js">var handlerThrows = { + setPrototypeOf(target, newProto) { + throw new Error('custom error'); + } +}; + +var newProto = {}, target = {}; + +var p2 = new Proxy(target, handlerThrows); +Object.setPrototypeOf(p2, newProto); // throws new Error("custom error") +Reflect.setPrototypeOf(p2, newProto); // throws new Error("custom error")</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v', '[[SetPrototypeOf]]')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v', '[[SetPrototypeOf]]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Proxy.handler.setPrototypeOf")}}</p> +</div> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> + <li>{{jsxref("Proxy.handler", "handler")}}</li> + <li>{{jsxref("Object.setPrototypeOf()")}}</li> + <li>{{jsxref("Reflect.setPrototypeOf()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/index.html new file mode 100644 index 0000000000..f9059ade82 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/index.html @@ -0,0 +1,435 @@ +--- +title: Proxy +slug: Web/JavaScript/Reference/Global_Objects/Proxy +tags: + - ECMAScript 2015 + - JavaScript + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy +--- +<div>{{JSRef}}</div> + +<p><strong>Proxy</strong> 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。</p> + +<h2 id="术语">术语</h2> + +<dl> + <dt>{{jsxref("Global_Objects/Proxy/handler", "<dfn>handler</dfn>")}}</dt> + <dd>包含捕捉器(trap)的占位符对象,可译为处理器对象。</dd> + <dt><dfn>traps</dfn></dt> + <dd>提供属性访问的方法。这类似于操作系统中捕获器的概念。</dd> + <dt><dfn>target</dfn></dt> + <dd>被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。</dd> +</dl> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate">const <var>p</var> = new Proxy(<var>target</var>, <var>handler</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code><var>target</var></code></dt> + <dd>要使用 <code>Proxy</code> 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。</dd> + <dt><code><var>handler</var></code></dt> + <dd>一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 <code><var>p</var></code> 的行为。</dd> +</dl> + +<h2 id="方法">方法</h2> + +<dl> + <dt>{{jsxref("Proxy.revocable()")}}</dt> + <dd>创建一个可撤销的<code>Proxy</code>对象。</dd> +</dl> + +<h2 id="handler_对象的方法">handler 对象的方法</h2> + +<p><code><var>handler</var></code> 对象是一个容纳一批特定属性的占位符对象。它包含有 <code>Proxy</code> 的各个捕获器(trap)。</p> + +<p>所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。</p> + +<dl> + <dt>{{JSxRef("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}</dt> + <dd>{{JSxRef("Object.getPrototypeOf")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}</dt> + <dd>{{JSxRef("Object.setPrototypeOf")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}}</dt> + <dd>{{JSxRef("Object.isExtensible")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}}</dt> + <dd>{{JSxRef("Object.preventExtensions")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}</dt> + <dd>{{JSxRef("Object.getOwnPropertyDescriptor")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}}</dt> + <dd>{{JSxRef("Object.defineProperty")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/has", "handler.has()")}}</dt> + <dd>{{JSxRef("Operators/in", "in")}} 操作符的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/get", "handler.get()")}}</dt> + <dd>属性读取操作的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/set", "handler.set()")}}</dt> + <dd>属性设置操作的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}}</dt> + <dd>{{JSxRef("Operators/delete", "delete")}} 操作符的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}}</dt> + <dd>{{JSxRef("Object.getOwnPropertyNames")}} 方法和 {{JSxRef("Object.getOwnPropertySymbols")}} 方法的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/apply", "handler.apply()")}}</dt> + <dd>函数调用操作的捕捉器。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/handler/construct", "handler.construct()")}}</dt> + <dd>{{JSxRef("Operators/new", "new")}} 操作符的捕捉器。</dd> +</dl> + +<p>一些不标准的捕捉器已经被<a href="/zh-CN/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#Proxy">废弃并且移除</a>了。</p> + +<h2 id="示例">示例</h2> + +<h3 id="基础示例">基础示例</h3> + +<p>在以下简单的例子中,当对象中不存在属性名时,默认返回值为 <code>37</code>。下面的代码以此展示了 {{jsxref("Global_Objects/Proxy/handler/get", "get")}} handler 的使用场景。</p> + +<pre class="brush: js notranslate">const handler = { + get: function(obj, prop) { + return prop in obj ? obj[prop] : 37; + } +}; + +const p = new Proxy({}, handler); +p.a = 1; +p.b = undefined; + +console.log(p.a, p.b); // 1, undefined +console.log('c' in p, p.c); // false, 37 +</pre> + +<h3 id="无操作转发代理">无操作转发代理</h3> + +<p>在以下例子中,我们使用了一个原生 JavaScript 对象,代理会将所有应用到它的操作转发到这个对象上。</p> + +<pre class="brush: js notranslate">let target = {}; +let p = new Proxy(target, {}); + +p.a = 37; // 操作转发到目标 + +console.log(target.a); // 37. 操作已经被正确地转发 +</pre> + +<h3 id="验证">验证</h3> + +<p>通过代理,你可以轻松地验证向一个对象的传值。下面的代码借此展示了 {{jsxref("Global_Objects/Proxy/handler/set", "set")}} handler 的作用。</p> + +<pre class="brush: js notranslate">let validator = { + set: function(obj, prop, value) { + if (prop === 'age') { + if (!Number.isInteger(value)) { + throw new TypeError('The age is not an integer'); + } + if (value > 200) { + throw new RangeError('The age seems invalid'); + } + } + + // The default behavior to store the value + obj[prop] = value; + + // 表示成功 + return true; + } +}; + +let person = new Proxy({}, validator); + +person.age = 100; + +console.log(person.age); +// 100 + +person.age = 'young'; +// 抛出异常: Uncaught TypeError: The age is not an integer + +person.age = 300; +// 抛出异常: Uncaught RangeError: The age seems invalid +</pre> + +<h3 id="扩展构造函数">扩展构造函数</h3> + +<p>方法代理可以轻松地通过一个新构造函数来扩展一个已有的构造函数。这个例子使用了<a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/construct"><code>construct</code></a>和<code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/apply">apply</a></code>。</p> + +<pre class="brush: js notranslate">function extend(sup, base) { + var descriptor = Object.getOwnPropertyDescriptor( + base.prototype, "constructor" + ); + base.prototype = Object.create(sup.prototype); + var handler = { + construct: function(target, args) { + var obj = Object.create(base.prototype); + this.apply(target, obj, args); + return obj; + }, + apply: function(target, that, args) { + sup.apply(that, args); + base.apply(that, args); + } + }; + var proxy = new Proxy(base, handler); + descriptor.value = proxy; + Object.defineProperty(base.prototype, "constructor", descriptor); + return proxy; +} + +var Person = function (name) { + this.name = name +}; + +var Boy = extend(Person, function (name, age) { + this.age = age; +}); + +Boy.prototype.sex = "M"; + +var Peter = new Boy("Peter", 13); +console.log(Peter.sex); // "M" +console.log(Peter.name); // "Peter" +console.log(Peter.age); // 13</pre> + +<h3 id="操作_DOM_节点">操作 DOM 节点</h3> + +<p>有时,我们可能需要互换两个不同的元素的属性或类名。下面的代码以此为目标,展示了 {{jsxref("Global_Objects/Proxy/handler/set", "set")}} handler 的使用场景。</p> + +<pre class="brush: js notranslate">let view = new Proxy({ + selected: null +}, { + set: function(obj, prop, newval) { + let oldval = obj[prop]; + + if (prop === 'selected') { + if (oldval) { + oldval.setAttribute('aria-selected', 'false'); + } + if (newval) { + newval.setAttribute('aria-selected', 'true'); + } + } + + // 默认行为是存储被传入 setter 函数的属性值 + obj[prop] = newval; + + // 表示操作成功 + return true; + } +}); + +let i1 = view.selected = document.getElementById('item-1'); +console.log(i1.getAttribute('aria-selected')); // 'true' + +let i2 = view.selected = document.getElementById('item-2'); +console.log(i1.getAttribute('aria-selected')); // 'false' +console.log(i2.getAttribute('aria-selected')); // 'true' +</pre> + +<h3 id="值修正及附加属性">值修正及附加属性</h3> + +<p>以下<code>products</code>代理会计算传值并根据需要转换为数组。这个代理对象同时支持一个叫做 <code>latestBrowser</code>的附加属性,这个属性可以同时作为 getter 和 setter。</p> + +<pre class="brush: js notranslate">let products = new Proxy({ + browsers: ['Internet Explorer', 'Netscape'] +}, { + get: function(obj, prop) { + // 附加一个属性 + if (prop === 'latestBrowser') { + return obj.browsers[obj.browsers.length - 1]; + } + + // 默认行为是返回属性值 + return obj[prop]; + }, + set: function(obj, prop, value) { + // 附加属性 + if (prop === 'latestBrowser') { + obj.browsers.push(value); + return; + } + + // 如果不是数组,则进行转换 + if (typeof value === 'string') { + value = [value]; + } + + // 默认行为是保存属性值 + obj[prop] = value; + + // 表示成功 + return true; + } +}); + +console.log(products.browsers); // ['Internet Explorer', 'Netscape'] +products.browsers = 'Firefox'; // 如果不小心传入了一个字符串 +console.log(products.browsers); // ['Firefox'] <- 也没问题, 得到的依旧是一个数组 + +products.latestBrowser = 'Chrome'; +console.log(products.browsers); // ['Firefox', 'Chrome'] +console.log(products.latestBrowser); // 'Chrome' +</pre> + +<h3 id="通过属性查找数组中的特定对象">通过属性查找数组中的特定对象</h3> + +<p>以下代理为数组扩展了一些实用工具。如你所见,通过 Proxy,我们可以灵活地“定义”属性,而不需要使用 {{jsxref("Object.defineProperties")}} 方法。以下例子可以用于通过单元格来查找表格中的一行。在这种情况下,target 是 <code><a href="/zh-CN/docs/DOM/table.rows">table.rows</a></code>。</p> + +<pre class="brush: js notranslate">let products = new Proxy([ + { name: 'Firefox' , type: 'browser' }, + { name: 'SeaMonkey' , type: 'browser' }, + { name: 'Thunderbird', type: 'mailer' } +], { + get: function(obj, prop) { + // 默认行为是返回属性值, prop ?通常是一个整数 + if (prop in obj) { + return obj[prop]; + } + + // 获取 products 的 number; 它是 products.length 的别名 + if (prop === 'number') { + return obj.length; + } + + let result, types = {}; + + for (let product of obj) { + if (product.name === prop) { + result = product; + } + if (types[product.type]) { + types[product.type].push(product); + } else { + types[product.type] = [product]; + } + } + + // 通过 name 获取 product + if (result) { + return result; + } + + // 通过 type 获取 products + if (prop in types) { + return types[prop]; + } + + // 获取 product type + if (prop === 'types') { + return Object.keys(types); + } + + return undefined; + } +}); + +console.log(products[0]); // { name: 'Firefox', type: 'browser' } +console.log(products['Firefox']); // { name: 'Firefox', type: 'browser' } +console.log(products['Chrome']); // undefined +console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }] +console.log(products.types); // ['browser', 'mailer'] +console.log(products.number); // 3 +</pre> + +<h3 id="一个完整的_traps_列表示例">一个完整的 <code>traps</code> 列表示例</h3> + +<p>出于教学目的,这里为了创建一个完整的 traps 列表示例,我们将尝试代理化一个非原生对象,这特别适用于这类操作:由 <a href="/zh-CN/docs/DOM/document.cookie#A_little_framework.3A_a_complete_cookies_reader.2Fwriter_with_full_unicode_support">发布在 document.cookie页面上的“小型框架”</a>创建的<code>docCookies</code>全局对象。</p> + +<pre class="brush: js notranslate">/* + var docCookies = ... get the "docCookies" object here: + https://developer.mozilla.org/zh-CN/docs/DOM/document.cookie#A_little_framework.3A_a_complete_cookies_reader.2Fwriter_with_full_unicode_support +*/ + +var docCookies = new Proxy(docCookies, { + "get": function (oTarget, sKey) { + return oTarget[sKey] || oTarget.getItem(sKey) || undefined; + }, + "set": function (oTarget, sKey, vValue) { + if (sKey in oTarget) { return false; } + return oTarget.setItem(sKey, vValue); + }, + "deleteProperty": function (oTarget, sKey) { + if (sKey in oTarget) { return false; } + return oTarget.removeItem(sKey); + }, + "enumerate": function (oTarget, sKey) { + return oTarget.keys(); + }, + "ownKeys": function (oTarget, sKey) { + return oTarget.keys(); + }, + "has": function (oTarget, sKey) { + return sKey in oTarget || oTarget.hasItem(sKey); + }, + "defineProperty": function (oTarget, sKey, oDesc) { + if (oDesc && "value" in oDesc) { oTarget.setItem(sKey, oDesc.value); } + return oTarget; + }, + "getOwnPropertyDescriptor": function (oTarget, sKey) { + var vValue = oTarget.getItem(sKey); + return vValue ? { + "value": vValue, + "writable": true, + "enumerable": true, + "configurable": false + } : undefined; + }, +}); + +/* Cookies 测试 */ + +alert(docCookies.my_cookie1 = "First value"); +alert(docCookies.getItem("my_cookie1")); + +docCookies.setItem("my_cookie1", "Changed value"); +alert(docCookies.my_cookie1);</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-proxy-objects', 'Proxy')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES2016', '#sec-proxy-objects', 'Proxy')}}</td> + <td>{{Spec2('ES2016')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES2017', '#sec-proxy-objects', 'Proxy')}}</td> + <td>{{Spec2('ES2017')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-objects', 'Proxy')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div> + +<p>{{Compat("javascript.builtins.Proxy", 2)}}</p> + +<h2 id="参考">参考</h2> + +<ul> + <li><a class="external" href="http://jsconf.eu/2010/speaker/be_proxy_objects.html">"Proxies are awesome" Brendan Eich presentation at JSConf</a> (<a class="external" href="http://www.slideshare.net/BrendanEich/metaprog-5303821">slides</a>)</li> + <li><a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:proxies">ECMAScript Harmony Proxy proposal page</a> and <a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics">ECMAScript Harmony proxy semantics page</a></li> + <li><a class="external" href="http://soft.vub.ac.be/~tvcutsem/proxies/">Tutorial on proxies</a></li> + <li><a href="/zh-CN/docs/JavaScript/Old_Proxy_API">SpiderMonkey specific Old Proxy API</a></li> + <li>{{jsxref("Object.watch()")}} is a non-standard feature but has been supported in Gecko for a long time.</li> +</ul> + +<h2 id="版权声明">版权声明</h2> + +<p>一些内容(如文本、例子)是复制自或修改自<a class="external" href="http://wiki.ecmascript.org/doku.php">ECMAScript wiki</a>(版权声明 <a class="external" href="http://creativecommons.org/licenses/by-nc-sa/2.0/">CC 2.0 BY-NC-SA</a>)。</p> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/proxy/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/proxy/index.html new file mode 100644 index 0000000000..71a257174f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/proxy/index.html @@ -0,0 +1,118 @@ +--- +title: Proxy() 构造器 +slug: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/Proxy +--- +<div>{{JSRef}}</div> + +<div> <code><strong>Proxy()</strong></code> 构造器用来创建 {{jsxref("Proxy")}} 对象。</div> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate">new Proxy(<var>target</var>, <var>handler</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code><var>target</var></code></dt> + <dd> <code>Proxy</code> 会对 target 对象进行包装。它可以是任何类型的对象,包括内置的数组,函数甚至是另一个代理对象。</dd> + <dt><code><var>handler</var></code></dt> + <dd>它是一个对象,它的属性提供了某些操作发生时所对应的处理函数。</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>我们可以使用 <code>Proxy()</code> 构造器来创建一个新的 <code>Proxy</code> 对象。 构造器接收两个主要参数:</p> + +<ul> + <li><code>target</code> 被代理的对象</li> + <li><code>handler</code> 被代理对象上的自定义行为</li> +</ul> + +<p>一个空的 <code>handler</code> 参数将会创建一个与被代理对象行为几乎完全相同的代理对象。通过在 <code>handler</code> 对象上定义一组处理函数,你可以自定义被代理对象的一些特定行为。例如, 通过定义 <code>get()</code> 你就可以自定义被代理对象的 <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors">属性访问器</a>。</p> + +<h3 id="处理函数">处理函数</h3> + +<p>本节列出了所有你可以自定义的处理函数。处理函数有时候也被成为“劫持”(traps),这是由于它们会对底层被代理对象的调用进行劫持。</p> + +<dl> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/apply", "handler.apply()")}}</dt> + <dd>函数调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/construct", "handler.construct()")}}</dt> + <dd>{{JSxRef("Operators/new", "new")}} 操作符劫持</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/defineProperty", "handler.defineProperty()")}}</dt> + <dd>{{JSxRef("Object.defineProperty")}}调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/deleteProperty", "handler.deleteProperty()")}}</dt> + <dd>{{JSxRef("Operators/delete", "delete")}} 操作符劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/get", "handler.get()")}}</dt> + <dd>获取属性值劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}</dt> + <dd>{{JSxRef("Object.getOwnPropertyDescriptor")}} 调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/getPrototypeOf", "handler.getPrototypeOf()")}}</dt> + <dd>{{JSxRef("Object.getPrototypeOf")}}调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/has", "handler.has()")}}</dt> + <dd>{{JSxRef("Operators/in", "in")}} 操作符劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/isExtensible", "handler.isExtensible()")}}</dt> + <dd> {{JSxRef("Object.isExtensible")}}调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/ownKeys", "handler.ownKeys()")}}</dt> + <dd>{{JSxRef("Object.getOwnPropertyNames")}} 和{{JSxRef("Object.getOwnPropertySymbols")}}调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/preventExtensions", "handler.preventExtensions()")}}</dt> + <dd>{{JSxRef("Object.preventExtensions")}}调用劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/set", "handler.set()")}}</dt> + <dd>设置属性值劫持。</dd> + <dt>{{JSxRef("Global_Objects/Proxy/Proxy/setPrototypeOf", "handler.setPrototypeOf()")}}</dt> + <dd>{{JSxRef("Object.setPrototypeOf")}}调用劫持。</dd> +</dl> + +<h2 id="示例">示例</h2> + +<h3 id="选择性代理属性访问器">选择性代理属性访问器</h3> + +<p>本例中,被代理对象有两个属性: <code>notProxied</code> 和 <code>proxied</code> 。我们定义了一个处理函数,它为 <code>proxied</code> 属性返回一个不同的值,而其他属性返回原值。</p> + +<pre class="brush: js notranslate">const target = { + notProxied: "original value", + proxied: "original value" +}; + +const handler = { + get: function(target, prop, receiver) { + if (prop === "proxied") { + return "replaced value"; + } + return Reflect.get(...arguments); + } +}; + +const proxy = new Proxy(target, handler); + +console.log(proxy.notProxied); // "original value" +console.log(proxy.proxied); // "replaced value"</pre> + +<h2 id="标准">标准</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-proxy-constructor', 'Proxy constructor')}}</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Proxy.Proxy")}}</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Meta_programming"><code>Proxy</code> and <code>Reflect</code> in the JavaScript Guide</a></li> + <li>{{jsxref("Global_Objects/Reflect", "Reflect")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/proxy/revocable/index.html b/files/zh-cn/web/javascript/reference/global_objects/proxy/revocable/index.html new file mode 100644 index 0000000000..5f0095ae65 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/proxy/revocable/index.html @@ -0,0 +1,89 @@ +--- +title: Proxy.revocable() +slug: Web/JavaScript/Reference/Global_Objects/Proxy/revocable +tags: + - ECMAScript6 + - JavaScript + - Method + - Proxy +translation_of: Web/JavaScript/Reference/Global_Objects/Proxy/revocable +--- +<div>{{JSRef("Global_Objects", "Proxy")}}</div> + +<p><code><strong>Proxy.revocable()</strong></code> 方法可以用来创建一个可撤销的代理对象。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox">Proxy.revocable(target, handler); +</pre> + +<dl> + <dt><code>target</code></dt> + <dd>将用 <code>Proxy</code> 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象。</dd> + <dt><code>handler</code></dt> + <dd>一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>返回一个包含了代理对象本身和它的撤销方法的可撤销 <code>Proxy</code> 对象。</p> + +<h2 id="描述">描述</h2> + +<p>该方法的返回值是一个对象,其结构为: <code>{"proxy": proxy, "revoke": revoke}</code>,其中:</p> + +<dl> + <dt><code>proxy</code></dt> + <dd>表示新生成的代理对象本身,和用一般方式 <code>new Proxy(target, handler)</code> 创建的代理对象没什么不同,只是它可以被撤销掉。</dd> + <dt><code>revoke</code></dt> + <dd>撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。</dd> +</dl> + +<p>一旦某个代理对象被撤销,它将变得几乎完全不可调用,在它身上执行任何的<strong>可代理操作</strong>都会抛出 {{jsxref("TypeError")}} 异常(注意,可代理操作一共有 {{jsxref("Proxy", "14 种", "#Methods_of_the_handler_object")}},执行这 14 种操作以外的操作不会抛出异常)。一旦被撤销,这个代理对象便不可能被直接恢复到原来的状态,同时和它关联的<strong>目标对象</strong>以及<strong>处理器对象</strong>都有可能被垃圾回收掉。再次调用撤销方法 <code>revoke()</code> 则不会有任何效果,但也不会报错。</p> + +<h2 id="示例">示例</h2> + +<pre class="brush: js">var revocable = Proxy.revocable({}, { + get(target, name) { + return "[[" + name + "]]"; + } +}); +var proxy = revocable.proxy; +proxy.foo; // "[[foo]]" + +revocable.revoke(); + +console.log(proxy.foo); // 抛出 TypeError +proxy.foo = 1 // 还是 TypeError +delete proxy.foo; // 又是 TypeError +typeof proxy // "object",因为 typeof 不属于可代理操作 +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范名称</th> + <th scope="col">规范状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-proxy.revocable', 'Proxy Revocation Functions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Proxy.revocable")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Proxy")}}</li> +</ul> |