日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ES6-proxy

發(fā)布時間:2024/8/26 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ES6-proxy 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

我們或多或少都聽過“數(shù)據(jù)綁定”這個詞,“數(shù)據(jù)綁定”的關鍵在于監(jiān)聽數(shù)據(jù)的變化,可是對于這樣一個對象:var obj = {value: 1},我們該怎么知道 obj 發(fā)生了改變呢?

definePropety

ES5 提供了 Object.defineProperty 方法,該方法可以在一個對象上定義一個新屬性,或者修改一個對象的現(xiàn)有屬性,并返回這個對象。

語法

Object.defineProperty(obj, prop, descriptor)

參數(shù)

obj: 要在其上定義屬性的對象。prop: 要定義或修改的屬性的名稱。descriptor: 將被定義或修改的屬性的描述符。

舉個例子:

var obj = {}; Object.defineProperty(obj, "num", {value : 1, writable : true, enumerable : true, configurable : true }); // 對象 obj 擁有屬性 num,值為 1

雖然我們可以直接添加屬性和值,但是使用這種方式,我們能進行更多的配置。

函數(shù)的第三個參數(shù) descriptor 所表示的屬性描述符有兩種形式:數(shù)據(jù)描述符和存取描述符

兩者均具有以下兩種鍵值

configurable

當且僅當該屬性的 configurable true 時,該屬性描述符才能夠被改變,也能夠被刪除。默認為 false

enumerable

當且僅當該屬性的 enumerable true 時,該屬性才能夠出現(xiàn)在對象的枚舉屬性中。默認為 false

數(shù)據(jù)描述符同時具有以下可選鍵值

value

該屬性對應的值。可以是任何有效的 JavaScript 值(數(shù)值,對象,函數(shù)等)。默認為 undefined。

writable

當且僅當該屬性的 writable true 時,該屬性才能被賦值運算符改變。默認為 false

存取描述符同時具有以下可選鍵值

get

一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。該方法返回值被用作屬性值。默認為 undefined。

set

一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。該方法將接受唯一參數(shù),并將該參數(shù)的新值分配給該屬性。默認為 undefined。

值得注意的是:

屬性描述符必須是數(shù)據(jù)描述符或者存取描述符兩種形式之一,不能同時是兩者。這就意味著你可以:

Object.defineProperty({}, "num", {value: 1, writable: true, enumerable: true, configurable: true });

也可以:

var value = 1; Object.defineProperty({}, "num", { get : function(){ return value; }, set : function(newValue){ value = newValue; }, enumerable : true, configurable : true });

但是不可以:

// 報錯 Object.defineProperty({}, "num", {value: 1, get: function() { return 1; } });

此外,所有的屬性描述符都是非必須的,但是 descriptor 這個字段是必須的,如果不進行任何配置,你可以這樣:

var obj = Object.defineProperty({}, "num", {}); console.log(obj.num); // undefined

Setters 和 Getters

之所以講到 defineProperty,是因為我們要使用存取描述符中的 get 和 set,這兩個方法又被稱為 getter 和 setter。由 getter 和 setter 定義的屬性稱做”存取器屬性“。

當程序查詢存取器屬性的值時,JavaScript 調(diào)用 getter方法。這個方法的返回值就是屬性存取表達式的值。當程序設置一個存取器屬性的值時,JavaScript 調(diào)用 setter 方法,將賦值表達式右側(cè)的值當做參數(shù)傳入 setter。從某種意義上講,這個方法負責“設置”屬性值。可以忽略 setter 方法的返回值。

舉個例子:

var obj = {}, value = null; Object.defineProperty(obj, "num", { get: function(){ console.log('執(zhí)行了 get 操作') return value; }, set: function(newValue) { console.log('執(zhí)行了 set 操作') value = newValue; } }) obj.value = 1 // 執(zhí)行了 set 操作 console.log(obj.value); // 執(zhí)行了 get 操作 // 1

這不就是我們要的監(jiān)控數(shù)據(jù)改變的方法嗎?我們再來封裝一下:

function Archiver() { var value = null; // archive n. 檔案 var archive = []; Object.defineProperty(this, 'num', { get: function() { console.log('執(zhí)行了 get 操作') return value; }, set: function(value) { console.log('執(zhí)行了 set 操作') value = value; archive.push({ val: value }); } }); this.getArchive = function() { return archive; }; } var arc = new Archiver(); arc.num; // 執(zhí)行了 get 操作 arc.num = 11; // 執(zhí)行了 set 操作 arc.num = 13; // 執(zhí)行了 set 操作 console.log(arc.getArchive()); // [{ val: 11 }, { val: 13 }]

watch API

既然可以監(jiān)控數(shù)據(jù)的改變,那我可以這樣設想,即當數(shù)據(jù)改變的時候,自動進行渲染工作。舉個例子:

HTML 中有個 span 標簽和 button 標簽

<span id="container">1</span> <button id="button">點擊加 1</button>

當點擊按鈕的時候,span 標簽里的值加 1。

傳統(tǒng)的做法是:

document.getElementById('button').addEventListener("click", function(){ var container = document.getElementById("container"); container.innerHTML = Number(container.innerHTML) + 1; });

如果使用了 defineProperty:

var obj = {value: 1 }// 儲存 obj.value 的值 var value = 1; Object.defineProperty(obj, "value", { get: function() { return value; }, set: function(newValue) { value = newValue; document.getElementById('container').innerHTML = newValue; } }); document.getElementById('button').addEventListener("click", function() { obj.value += 1; });

代碼看似增多了,但是當我們需要改變 span 標簽里的值的時候,直接修改 obj.value 的值就可以了。

然而,現(xiàn)在的寫法,我們還需要單獨聲明一個變量存儲 obj.value 的值,因為如果你在 set 中直接?obj.value = newValue就會陷入無限的循環(huán)中。此外,我們可能需要監(jiān)控很多屬性值的改變,要是一個一個寫,也很累吶,所以我們簡單寫個 watch 函數(shù)。使用效果如下:

var obj = {value: 1 }watch(obj, "num", function(newvalue){ document.getElementById('container').innerHTML = newvalue; }) document.getElementById('button').addEventListener("click", function(){ obj.value += 1 });

我們來寫下這個 watch 函數(shù):

(function(){var root = this; function watch(obj, name, func){ var value = obj[name]; Object.defineProperty(obj, name, { get: function() { return value; }, set: function(newValue) { value = newValue; func(value) } }); if (value) obj[name] = value } this.watch = watch; })()

現(xiàn)在我們已經(jīng)可以監(jiān)控對象屬性值的改變,并且可以根據(jù)屬性值的改變,添加回調(diào)函數(shù),棒棒噠~

proxy

使用 defineProperty 只能重定義屬性的讀取(get)和設置(set)行為,到了 ES6,提供了 Proxy,可以重定義更多的行為,比如 in、delete、函數(shù)調(diào)用等更多行為。

Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,ES6 原生提供 Proxy 構(gòu)造函數(shù),用來生成 Proxy 實例。我們來看看它的語法:

var?proxy =?new?Proxy(target, handler);

proxy 對象的所有用法,都是上面這種形式,不同的只是handler參數(shù)的寫法。其中,new Proxy()表示生成一個Proxy實例,target參數(shù)表示所要攔截的目標對象,handler參數(shù)也是一個對象,用來定制攔截行為。

var proxy = new Proxy({}, {get: function(obj, prop) { console.log('設置 get 操作') return obj[prop]; }, set: function(obj, prop, value) { console.log('設置 set 操作') obj[prop] = value; } }); proxy.time = 35; // 設置 set 操作 console.log(proxy.time); // 設置 get 操作 // 35

除了 get 和 set 之外,proxy 可以攔截多達 13 種操作,比如 has(target, propKey),可以攔截 propKey in proxy 的操作,返回一個布爾值。

// 使用 has 方法隱藏某些屬性,不被 in 運算符發(fā)現(xiàn) var handler = {has (target, key) {if (key[0] === '_') { return false; } return key in target; } }; var target = { _prop: 'foo', prop: 'foo' }; var proxy = new Proxy(target, handler); console.log('_prop' in proxy); // false

又比如說 apply 方法攔截函數(shù)的調(diào)用、call 和 apply 操作。

apply 方法可以接受三個參數(shù),分別是目標對象、目標對象的上下文對象(this)和目標對象的參數(shù)數(shù)組,不過這里我們簡單演示一下:

var target = function () { return 'I am the target'; }; var handler = { apply: function () { return 'I am the proxy'; } }; var p = new Proxy(target, handler); p(); // "I am the proxy"

又比如說 ownKeys 方法可以攔截對象自身屬性的讀取操作。具體來說,攔截以下操作:

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()

下面的例子是攔截第一個字符為下劃線的屬性名,不讓它被 for of 遍歷到。

let target = {_bar: 'foo',_prop: 'bar', prop: 'baz' }; let handler = { ownKeys (target) { return Reflect.ownKeys(target).filter(key => key[0] !== '_'); } }; let proxy = new Proxy(target, handler); for (let key of Object.keys(proxy)) { console.log(target[key]); } // "baz"

更多的攔截行為可以查看阮一峰老師的?《ECMAScript 6 入門》

值得注意的是,proxy 的最大問題在于瀏覽器支持度不夠,而且很多效果無法使用 poilyfill 來彌補。

watch API 優(yōu)化

我們使用 proxy 再來寫一下 watch 函數(shù)。使用效果如下:

(function() {var root = this; function watch(target, func) { var proxy = new Proxy(target, { get: function(target, prop) { return target[prop]; }, set: function(target, prop, value) { target[prop] = value; func(prop, value); } }); if(target[name]) proxy[name] = value; return proxy; } this.watch = watch; })() var obj = { value: 1 } var newObj = watch(obj, function(key, newvalue) { if (key == 'value') document.getElementById('container').innerHTML = newvalue; }) document.getElementById('button').addEventListener("click", function() { newObj.value += 1 });

我們也可以發(fā)現(xiàn),使用 defineProperty 和 proxy 的區(qū)別,當使用 defineProperty,我們修改原來的 obj 對象就可以觸發(fā)攔截,而使用 proxy,就必須修改代理對象,即 Proxy 的實例才可以觸發(fā)攔截。

?


https://segmentfault.com/a/1190000016959805

轉(zhuǎn)載于:https://www.cnblogs.com/qdcnbj/p/9945390.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結(jié)

以上是生活随笔為你收集整理的ES6-proxy的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 可以看av的网址 | 久久久久久久香蕉 | 大黑人交交护士xxxxhd | 欧美老熟 | 色婷婷精品久久二区二区密 | 久久国精品 | 中文字幕国产在线观看 | 日韩18p| 中文字幕伦理 | 日韩mv欧美mv国产网站 | 伊人网影院 | 精品欧美一区二区久久久 | aaa黄色片 | 自拍偷拍18p| 欧美在线色图 | 捆绑少妇玩各种sm调教 | 俺也来俺也去俺也射 | 国产裸体视频网站 | 成人av影院在线观看 | av中文一区| 青青操国产视频 | 在线观看中出 | 日韩欧美毛片 | 成人午夜视频在线播放 | 97caoporn| 精品视频一二 | 亚洲国产乱 | 青青草精品在线 | 亚洲熟女一区 | 蜜桃导航-精品导航 | 古装做爰无遮挡三级 | 免费看黄色的视频 | 久久成人a | 伊人久久av | 公侵犯一区二区三区四区中文字幕 | 豆花在线观看 | 日韩国产欧美综合 | 国产3级在线 | 国产第一页屁屁影院 | 99热久| 在线免费黄色av | 国产中文字幕免费 | 97精品人妻一区二区三区 | 激情五月激情综合网 | 国产成人免费看一级大黄 | 中文字幕一区二区三区人妻 | 深夜福利视频网站 | 久久加久久 | 国产在线播放网站 | 久久久久久久久久网站 | 国产黄色www | 先锋资源一区二区 | 国产精品国产馆在线真实露脸 | 中文字幕av一区 | 国产靠逼视频 | 国产图片区 | 亚洲综合网在线观看 | 麻豆福利在线观看 | 天天爱夜夜爽 | 在线精品一区二区 | 亚洲乱码国产乱码精品精的特点 | 亚洲天堂黄色 | 一级片免费 | 免费超碰在线观看 | 毛片视频在线免费观看 | 精品熟妇视频一区二区三区 | 精品处破女学生 | 欧美极品少妇xxxxⅹ喷水 | 欧美国产视频一区 | 国产在线日本 | 九草av| 91片黄在线观看喷潮 | 国产xxxxxxxxx| 成人在线一区二区三区 | 久操免费在线 | 午夜视频福利 | 亚洲日本久久 | 久久影业| 青娱乐97| 海角国产乱辈乱精品视频 | 尤物在线观看 | 齐天大性床战铁扇公主 | 操韩国美女 | 九九精品视频在线观看 | 一本大道东京热无码aⅴ | 亚洲好视频 | 蜜桃色av| 国内性视频 | 日韩一区二区视频 | 孕妇一级片 | h视频网站在线观看 | 裸体裸乳免费看 | 欧美11p | 色偷av| 麻豆app在线观看 | 色玖玖 | 亚洲激情 | 日韩欧美高清一区 | 亚洲成人生活片 |