摘要:關于有人說我用刪除這個屬性不就好了之后打印發(fā)現(xiàn)它還是一只哈士奇。如下的解釋如下操作符會從某個對象上移除指定屬性。
javascript-Object-Property
? javascript-對象的屬性的延伸學習
前言在學習vue數(shù)據(jù)綁定的較底層原理時,被setter和getter困惑了很久,一路追根溯源,通過閱讀《你不知道的javascript》和紅寶書理解了迷惑我的setter、getter。
首先了解什么是屬性描述符[](http://xurenjie.cn:3000/img/d...
在ES5之前,javascript語言沒有提供可以檢驗屬性特性的方法,是否只讀?不知道;是否可配置?不知道;是否能用for in枚舉?不知道。
ES5之后就有了如下的屬性描述符:
var Dogger = { breed: "柴犬" } Object.getOwnPropertyDescriptor( Dogger , "breed" );
輸出:
{ value: "柴犬", writable: true, configurable: true, enumerable: true }
在這,創(chuàng)建了一個品種為柴犬的dogger。[[Value]]特性將設置為"柴犬",之后操作對breed的任何修改將反映到這個位置。對,沒錯,這個getOwnPropertyDescriptor( Dogger , "breed" )函數(shù)就是我們要的檢驗屬性特性的方法。
默認:在創(chuàng)建普通對象屬性時,屬性描述符會使用默認值,即可寫可配可枚舉。(都為true)
下面分別介紹一下、這幾個屬性
writeable決定是否修改屬性的值,是否可以指定新的值給它
Dogger.breed = "哈士奇"
很好理解,當writeable為false的時候,其實定義了一個空的setter(等會會提),這個操作將無效,在嚴格模式下會拋出一個TypeError的錯誤。
configurable與configurable緊密相連的就是defineProperty( )這個方法了,當configurable: false 將不可使用‘好基友’defineProperty( )來配置。后面還會介紹一個會受影響的delete。
var Dogger = { breed: "柴犬" } Object.defineProperty( Dogger, "breed", { value: "哈士奇", writable: true, configurable: false, enumerable: true } ) Dogger.breed // "哈士奇" | 哈哈!我變成了一只哈士奇 Object.defineProperty( Dogger, "breed", { value: "柴犬", writable: true, configurable: true, enumerable: true } ) // TypeError
這只作死的柴犬在通過defineProperty( )把自己配置成哈士奇之后,順便把configurable修改為false,這樣之后defineProperty( )不管是否嚴格模式都將報TypeError的錯誤,這是單向操作,無法撤銷。 一失足成千古恨~
[](http://xurenjie.cn:3000/img/d...
還是可以通過writable的方式修改breed的嘛~,不過這里有一個方法可以讓dogger徹底絕望,使breed無法修改,也就是這個例外:這個時候defineProperty( )還是可以使用的(如下),只可以修改writable,configurable需要與剛才的false一致。
Object.defineProperty( Dogger, "breed", { value: "哈士奇", writable: false, configurable: false, enumerable: true } )
這樣之后柴犬永遠變成了只哈士奇。
[](http://xurenjie.cn:3000/img/d...
有人說我用delete刪除這個breed屬性不就好了?
delete Dogger.breed
之后打印dogger發(fā)現(xiàn)它還是一只哈士奇。如下:
MDN的解釋如下
delete 操作符會從某個對象上移除指定屬性。成功刪除的時候回返回 true,否則返回 false。
Non-configurable properties cannot be removed. This includes properties ofbuilt-in objects like Math, Array, Object and properties that are created as non-configurable with methods like Object.defineProperty( ).
When in strict mode, if delete is used on a direct reference to a variable, a function argument or a function name, it will throw a SyntaxError.
Any variable defined with var is marked as non-configurable. In the following example, salary is non-configurable and cannot be deleted. In non-strict mode, the delete operation will return false.
delete只是用來直接刪除對象(可刪除的)屬性,當breed屬性是Dogger的最后引用者,對這個屬性執(zhí)行delete操作,這個為引用的對象就可以被垃圾回收了,不要看成一個釋放內存的工具,而是刪除屬性的操作,僅此。
enumerable當且僅當該屬性的 enumerable 為 true 時,該屬性才能夠出現(xiàn)在對象的枚舉屬性中。默認為 false。
屬性特性 enumerable 定義了對象的屬性是否可以在 for...in 循環(huán)和 Object.keys( ) 中被枚舉。
放上MDN的代碼片段:
[ [ Get ] ]和[ [ Put ] ] [ [ Get ] ]var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable:true });
Object.defineProperty(o, "b", { value : 2, enumerable:false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable defaults to false
o.d = 4; // 如果使用直接賦值的方式創(chuàng)建對象的屬性,則這個屬性的enumerable為truefor (var i in o) {
console.log(i);
}
// 打印 "a" 和 "d" (in undefined order)Object.keys(o); // ["a", "d"]
o.propertyIsEnumerable("a"); // true
o.propertyIsEnumerable("b"); // false
o.propertyIsEnumerable("c"); // false
Dogger.breed
如上,對一個對象進行訪問時有一個很重要的細節(jié)。Dogger.breed是一次屬性訪問,但并不是僅僅在Dogger中查找breed,其實看起來更像是在語言規(guī)范中執(zhí)行了Dogger的[ [ Get ] ]操作,看上去像[ [ Get ] ]( )。
在對象中查找有沒有這個屬性。
在該對象的原型鏈上查找有沒有這個屬性。
都沒找到返回undefined(注意:如果那個屬性值恰好為undefined時,雖然返回值一樣,但是底層發(fā)生的事是不一樣的)
[ [ Put ] ][ [ Get ] ]對應[ [ Put ] ]操作,一旦給對象屬性賦值就觸發(fā)設置和創(chuàng)建這個屬性發(fā)生的事情是這樣的:
首先確定是否存在這個屬性。breed是否存在
存在,是否是setter。是setter就調用setter,是否是setter來給breed賦值
writable是否為false,false則無效。breed的writable是否為false
設置值為該屬性的值
Getter和Setter在《 javascript高級程序設計 》中成為訪問器屬性,也稱為訪問描述符,getter和setter是兩個隱形的函數(shù),getter為讀取屬性值的函數(shù),setter為設置屬性值的函數(shù),在訪問這個階段我們關注的是四個屬性:
set
get
configurable
enumerable
這時候我們用Dogger的例子來了解一下這些特性
var Dogger = { get breed() { ? ? ? ?return "柴犬" ? ?} } Object.defineProperty( Dogger "breed-type", { get: function() { ? ? ?return this.breed + "品種" } } ) Dogger.breed // "柴犬" Dogger.breed-type // "柴犬品種"
沒毛病,不管是隱式調用還是顯式確實能夠讓我們定義屬性,自動調用隱藏函數(shù),返回值為屬性訪問的返回值
[](http://xurenjie.cn:3000/img/d...
如果這時候,我們想用賦值操作給Dogger改變屬性會怎么樣?
Dogger.breed = "哈士奇" Dogger.breed // "柴犬"
由于只定義了breed的getter,所以對它的值進行設置時set操作會忽略賦值操作(也不會報錯)。其實就算定義了setter,自定義
的getter還是只會返回getter設置的值。
因此你去改變屬性的值時,你還需要定義一個setter,通常來說,他們是成雙成對的。不寫嚴格模式會報錯。
setter其實就是我們最常用的賦值操作
var Dogger = { get breed() { ? ? ? ?return "柴犬" ? ?} set breed(val) { ? ? ? ?this._breed_ = val ? ?} } Dogger.breed = "哈士奇" Dogger.breed // "哈士奇"
這樣一來,賦值操作就可以改變啦!我們把賦值操作存儲給新建的_breed_ ,只是一種慣例,通過setter可以改變對變量訪問值的處理規(guī)則。
如果不用_breed_,setter/getter的調用執(zhí)行時機class Dogger { constructor (name, breed) { this.name = name; this.breed = breed; } set breed (breed) { console.log("setter"); this.breed = breed; } get breed () { console.log("getter"); return this.breed; } } var dogger = new Dogger("忠犬八公", "柴犬");
代碼報錯了!!!這是因為,在構造函數(shù)中執(zhí)行this.breed = breed的時候,就會去調用set breed,在set breed方法中,我們又執(zhí)行this.breed = breed,進行無限遞歸,最后導致棧溢出(RangeError)。
因此,原來只要this.breed中的屬性名和set breed/get breed后面的breed一致,對this.breed就會調用setter/getter,也就是說setter/getter是hook函數(shù),而真實的存儲變量是_breed_,我們可以在代碼中直接獲取它。
ES6 的 proxyProxy可以理解成代理代辦,在目標對象之前架設一層“攔截”,劫持了外界對該對象的訪問和設置(setter和getter)。
借用最近看到的例子直接看代碼吧
const phoneHandler = { get (target,name) { console.log(`正在讀取${name}`) //"0102101220".replace(/(d{3})(d{3})(d{4})/,"$1-$2-$3") //"010-210-1220" return target[name].replace(/([0-9]{3})(d{3})(d{4})/,"($1)-$2-$3") }, set (target, name, value) { console.log(`正在設置${name}`) // .match正則表達式的方法:匹配所有數(shù)字,全局匹配 target[name] = value.match(/[0-9]/g).join("") } } // 攔截對象,代理代辦,對空對象的代理 // 復雜對象 ajax 將代碼放在proxy中 const phoneNumber = new Proxy({}, phoneHandler) phoneNumber.phone = "電話:0102101220" console.log(phoneNumber.phone)
不難看出new出來的Proxy是對空對象的代理,這樣一來,setter和getter都被phoneHandler中的set和get包辦了,用于復雜對象, ajax, 將代碼放在proxy中代理。
參考你不知道的javascript
javascript高級程序設計
求star:https://github.com/renjie1996...
qq:2578370399
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82999.html
摘要:在模板中放入太多的邏輯會讓模板過重且難以維護。它會根據(jù)控件類型自動選取正確的方法來更新元素。指令需要使用的語法,指的是原數(shù)據(jù)數(shù)組,指的是迭代的數(shù)組元素。 注:本教程所使用的vue版本為 2.5.16 MVC與MVVM MVC(Model-View-Controller): M指的是從后臺獲取到的數(shù)據(jù), V指的是顯示動態(tài)數(shù)據(jù)的html頁面, C是指響應用戶操作、經(jīng)過業(yè)務邏輯處理后去更新...
摘要:指令帶有前綴,以表示它們是提供的特殊屬性。最后,我們需要為賦值世界舞王尼古拉斯趙四世界舞王尼古拉斯趙四初學就到這里了,相信你已經(jīng)在腦子里確定了的原理的概念也已經(jīng)非常清楚了,希望你能夠在學習的道路上越走越遠,最后感謝你的瀏覽。 vue.js vue介紹 Vue.js(讀音 /vju?/,類似于 view) 是一套構建用戶界面的漸進式框架。與其他重量級框架不同的是,Vue 采用自底向上增量...
摘要:如果我們作為一個后端開發(fā)者想掌握一個前端框架,是一個好選擇,因為它足夠的易學。是語言的下一代標準。數(shù)據(jù)方法生命周期鉤子函數(shù)其他有些內容比較重要,留到后面講定義數(shù)據(jù)定義數(shù)據(jù)定義了數(shù)據(jù),那么就可以在管理的區(qū)域中使用的獲取數(shù)據(jù)的語法來獲取數(shù)據(jù)。目錄 前言: iview組件庫示例 element組件庫示例 ...
摘要:當我們的視圖和數(shù)據(jù)任何一方發(fā)生變化的時候,我們希望能夠通知對方也更新,這就是所謂的數(shù)據(jù)雙向綁定。返回值返回傳入函數(shù)的對象,即第一個參數(shù)該方法重點是描述,對象里目前存在的屬性描述符有兩種主要形式數(shù)據(jù)描述符和存取描述符。 前言 談起當前前端最熱門的 js 框架,必少不了 Vue、React、Angular,對于大多數(shù)人來說,我們更多的是在使用框架,對于框架解決痛點背后使用的基本原理往往關注...
閱讀 4947·2021-11-25 09:43
閱讀 1193·2021-11-24 09:38
閱讀 1904·2021-09-30 09:54
閱讀 2812·2021-09-23 11:21
閱讀 2377·2021-09-10 10:51
閱讀 2377·2021-09-03 10:45
閱讀 1172·2019-08-30 15:52
閱讀 1775·2019-08-30 14:13