|
導讀微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一... 微信小程序,簡稱小程序,英文名Mini Program,是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應用。小程序是一種不用下載就能使用的應用,也是一項門檻非常高的創新,經過將近兩年的發展,已經構造了新的小程序開發環境和開發者生態。 元編程是指的是開發人員對 “語言本身進行編程”。一般是編程語言暴露了一些API,供開發人員來操作語言本身的某些特性。從ES6開始,新增了Proxy和 Reflect特性,擴展了元編程(Meta Programming)能力,允許攔截并定制基礎語言操作行為(比如,屬性查找,賦值,枚舉,函數調等)。 Proxy(代理) Proxy是ES6加入的一個新特性,它可以 “代理” 對象的原生行為,替換為執行自定義行為。 Proxy可以理解成在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。 Proxy 對象用來為基礎操作(例如:屬性查找、賦值、枚舉、方法調用等)定義用戶自定義行為。 創建一個Proxy對象:
target:目標對象,可以是任意類型的對象,比如數組,函數,甚至是另外一個代理對象。 handlert:處理器對象,包含了一組代理方法,分別控制所生成代理對象的各種行為。 Proxy對象的方法: Proxy.revocable(target, handler):用來創建一個可撤銷的代理對象。 處理器對象一共有14種可代理方法: handler.getPrototypeOf():在讀取代理對象的原型時觸發該操作,比如在執行 Object.getPrototypeOf(proxy) 時。 handler.setPrototypeOf():在設置代理對象的原型時觸發該操作,比如在執行 Object.setPrototypeOf(proxy, null) 時。 handler.isExtensible():在判斷一個代理對象是否是可擴展時觸發該操作,比如在執行 Object.isExtensible(proxy) 時。 handler.preventExtensions():在讓一個代理對象不可擴展時觸發該操作,比如在執行 Object.preventExtensions(proxy) 時。 handler.getOwnPropertyDescriptor():在獲取代理對象某個屬性的屬性描述時觸發該操作,比如在執行 Object.getOwnPropertyDescriptor(proxy, “foo”) 時。 handler.defineProperty():在定義代理對象某個屬性時的屬性描述時觸發該操作,比如在執行 Object.defineProperty(proxy, “foo”, {}) 時。 handler.has():在判斷代理對象是否擁有某個屬性時觸發該操作,比如在執行 “foo” in proxy 時。 handler.get():在讀取代理對象的某個屬性時觸發該操作,比如在執行 proxy.foo 時。 handler.set():在給代理對象的某個屬性賦值時觸發該操作,比如在執行 proxy.foo = 1 時。 handler.deleteProperty():在刪除代理對象的某個屬性時觸發該操作,比如在執行 delete proxy.foo 時。 handler.enumerate():在遍歷代理對象的屬性時觸發該操作,比如在執行 for(i in proxy){} 時。 handler.ownKeys():在獲取代理對象的所有屬性鍵時觸發該操作,比如在執行 Object.getOwnPropertyNames(proxy) 時。 handler.apply():在調用一個目標對象為函數的代理對象時觸發該操作,比如在執行 proxy() 時。 handler.construct():在給一個目標對象為構造函數的代理對象構造實例時觸發該操作,比如在執行new proxy() 時。 攔截屬性值的讀取操作:
上面代碼中,Proxy(代理)對象定義一個target和一個handle,handle實現了一個get捕捉方法。通過這個方法,被代理的對象對于未定義的屬性,不再返回undefined,而是返回一個42的數字。 攔截屬性值的賦值操作:
上面代碼中,設置了set的處理函數,如果我們偵聽的對象的屬性被更改,那這個處理程序就會被調用,同時通過參數能夠得知是哪個屬性被更改,更改為了什么值。 同一個攔截器函數,可以設置攔截多個操作:
Proxy.revocable方法用來創建一個可撤銷的代理對象,一旦某個代理對象被撤銷,它將變的幾乎完全不可用,在它身上執行任何的可代理操作都會拋出 TypeError 異常。
Reflect(反射) ES6 中引入的Reflect是另一個元編程的特性,它使得我們可以直接操縱對象的原生行為。Reflect可操縱的行為與Proxy可代理的行為是一一對應的,這使得可以在Proxy的自定義方法中方便的使用Reflect調用原生行為。 Reflection(反射)促進元編程的一種很有價值的語言特性,它可以在程序運行時動態展現程序本身的特性。 Reflect 對象提供了14個靜態方法,它們的名字剛好和那14個代理處理器方法的名字相同,這14個方法中有幾個剛好在 Object 對象身上也存在同名方法,雖然它們功能類似,但也存在細微差異。 Reflect.apply():對一個函數進行調用操作,同時可以傳入一個數組作為調用參數。和 Function.prototype.apply() 功能類似。 Reflect.construct():對構造函數進行 new 操作,相當于執行 new target(…args)。 Reflect.defineProperty():和 Object.defineProperty() 類似。 Reflect.deleteProperty():刪除對象的某個屬性,相當于執行 delete target[name]。 Reflect.enumerate():該方法會返回一個包含有目標對象身上所有可枚舉的自身字符串屬性以及繼承字符串屬性的迭代器,for…in 操作遍歷到的正是這些屬性。 Reflect.get():獲取對象身上某個屬性的值,類似于 target[name]。 Reflect.getOwnPropertyDescriptor():類似于 Object.getOwnPropertyDescriptor()。 Reflect.getPrototypeOf(): 類似于 Object.getPrototypeOf()。 Reflect.has():判斷一個對象是否存在某個屬性,和 in 運算符 的功能完全相同。 Reflect.isExtensible():類似于 Object.isExtensible()。 Reflect.ownKeys():返回一個包含所有自身屬性(不包含繼承屬性)的數組。 Reflect.preventExtensions():類似于 Object.preventExtensions()。 Reflect.set():設置對象身上某個屬性的值,類似于 target[name] = val。 Reflect.setPrototypeOf():類似于 Object.setPrototypeOf()。
上面代碼中,Proxy方法攔截target對象的屬性賦值行為,采用Reflect.set方法將值賦值給對象的屬性。 為什么要使用Reflect: 將Object對象的一些明顯屬于語言內部的方法(比如Object.defineProperty),放到Reflect對象上。現階段,某些方法同時在Object和Reflect對象上部署,未來的新方法將只部署在Reflect對象上。 修改某些Object方法的返回結果,讓其變得更合理。比如,Object.defineProperty(obj, name, desc)在無法定義屬性時,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)則會返回false。 讓Object操作都變成函數行為。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)讓它們變成了函數行為。 Reflect對象的方法與Proxy對象的方法一一對應,只要是Proxy對象的方法,就能在Reflect對象上找到對應的方法。這就讓Proxy對象可以方便地調用對應的Reflect方法,完成默認行為,作為修改行為的基礎。也就是說,不管Proxy怎么修改默認行為,你總可以在Reflect上獲取默認行為。
上面代碼中,每一個Proxy對象的攔截操作(get、delete、has),內部都調用對應的Reflect方法,保證原生行為能夠正常執行。添加的工作,就是將每一個操作輸出一行日志。有了Reflect對象以后,很多操作會更易讀。 以上就是ES6新特性開發微信小程序(6)的詳細內容,更多請關注php中文網其它相關文章! 小程序是一種不需要下載安裝即可使用的應用,它實現了應用“觸手可及”的夢想,用戶掃一掃或者搜一下即可打開應用。 |
溫馨提示:喜歡本站的話,請收藏一下本站!