探祕隱藏在物件中的get和set方法
當然如果要仔細看的話,大家可以:
var a = {}; console.log(a);
我們可以清晰的看到他有很多的內建方法。當然,也可以看到最下面有兩個比較怪的方法 get 和 set ,只要是物件就可以找到這兩個方法,但是究竟怎麼使用這兩個方法呢?
我自己研究了半天,發現可以這樣使用,就拿最簡單的物件 json 來舉例。
var Json = { set Leo(value){ console.log(value) } }; Json.Leo= 'liyou' //'liyou'
使用起來你會發現非常的怪異, 這個東西看起來像個函式,但是又必需賦值才能用。我們理解起來大概就是,只要一賦值,這個屬性就被從新賦予新的東西,而「這個」則是執行了這個函式。
那麼,到底他是不是函式呢?我們來繼續探索一下這個 set 。
typeof Json.Leo //undefined Json.Leo() //Error:Json.Leo is not a function
也就是說,「這個」東西不是作為他的私有屬性存在,而「這個」也不是函式。
繼續實驗的話,會發現「這個」東西只可以傳一個引數。
var Json = { • set Leo(value,nextValue){//Uncaught SyntaxError: Setter must have exactly one formal parameter.
程式碼提示一個只允許使用一個引數,也是說他只支援一個引數。當然,如果我們想傳很多的話,似乎也只能通過 json 。
var Json = { set Leo(...val){ //Uncaught SyntaxError: Setter function argument must not be a rest parameter console.log(val) } }; Json.Leo= 'liyou' 不支援 ES6 的不定陣列參,但是支援 arguments 。 var Json = { set Leo(val){ console.log(arguments[0]) } }; Json.Leo = 'liyou' //'liyou';
而 get 方法和他很接近,使用起來就像一個私有的屬性用起來一樣。
例如:
var Json = { set Leo(val){ console.log(arguments[0]) }, get Leo(){ console.log('liyou') } }; Json.Leo //'liyou';
當然我們可以看出來,如果賦值就會走 set ,如果沒有賦值就會走 get 。
值得一提的是, get 方法是不允許有引數的,一旦裡面放入一個引數,就會直接報錯。
雖然可以順利使 get 方法,但是如果我們想要找到「這個」東西到底,結果是我們依然找不到他。
Json.Leo //'liyou' typeof Json.Leo // undefined
簡而言之,一個內建的函式體可以使用,但是不能當作正常的一個私有屬性來判斷其資料型別。
那麼,如果這個函式體碰上了真正的私有屬性會變稱什麼樣呢?
例如:
var Json = { • get Leo(){ • return 10; • }, • Leo:20 }; console.log(Json.Leo)?
答案是 undefined 。其實也不難怪,因為似乎 js 也不知道你拿的是內建函式體還是私有屬性,而且似乎本來性質也不一樣,所以到頭來也只能給你一個 undefined 。
當然這裡面的 this 還是指向物件本身的。
例如:
var Json = { • get Leo(){ • return this • } }; Json.b = Json.Leo//
這個時候 json 下面就有無窮無盡的 b ,就像 window 下面有無窮的 window 一樣。
值得一提的是,「這個」東西只能手動的在寫物件的時候寫到裡面,而不能通過賦值去給予。
例如:
var a = {}; a['set Leo'] = function(){}//
這裡面的 set 和上文的 set 不是一個東西。
當然 json 中的 get/set 也可以迴圈使用。
例如:
var Json = { get Leo(){ return { get isTeacher(){ console.log('liyou') } } } } Json.Leo.isTeacher //'liyou'
「這個」東西不能在一般的函式中使用。
比如,function show(){set Leo(){}} // 報錯。雖然 new show() 裡面有這個內建函式,但是還是不能使用。
但是卻可以在 ES6 中的 class 物件中使用。
例如:
class Leo { constructor() { } get show() { return 'liyou'; } set show(value) { console.log('liyou: '+value); } } let inst = new Leo(); inst.show = 123; // liyou: 123 inst.show // 'liyou'
因為class 類本身也屬於函式物件,所以函式物件中有這個 get/set 內建函式,就不奇怪了。
總結