做爲一個前端新人,免不了加各類羣,和其餘小夥伴們一塊兒學習(chui bi),互相幫助(bi can)。前幾天一個小夥伴在羣裏發了道本身去面試的筆試題,我寫了一下,一時間沒能實現,今天又折騰了一下,雖然大體實現了,但不知道是否優雅,分享本身解法的同時也想請大佬指點一二。javascript
有一個name屬性,外部只能訪問不能修改,初始化時賦值。前端
內部維護一個叫things的局部變量,數組類型,用於存儲購買的物品(something)清單。java
有一個buy(something)方法,用於購買物品(something)面試
具備count屬性,用於指示一共買了多少物品。數組
看到這題的第一反應就是用構造函數/class來寫。Person對象應該就是一個Person類。
兩個屬性一個方法,嗯,沒什麼問題。只有2個點須要考慮:閉包
1、 這個things局部變量是個啥?是屬性嗎?函數
應該不是,既然特地指出了,確定有他的考慮,那麼既然是局部變量,外部也是訪問不到的,這個應該用閉包寫。學習
2、 name屬性外部只能訪問不能修改.ui
這個用閉包也能解決,可是這樣記不能經過構造函數/class來實現了,背離了初衷,不行(不過我後面仍是會給出這種寫法)。那麼(以個人水平)就只能用Proxy
或者class
,這2個都能攔截對象屬性的讀/寫。2種我都試過,採用Proxy,緣由下面會講。this
class Person { constructor(name,count=0) { this.name = name; this.count = count; this.init() } //初始化函數 init() { var things = []; Person.prototype.buy = (something) => { //爲了造成閉包,顯式將buy方法寫到Person的原型上 things.push(something); this.count = things.length; } } } //Proxy handler對象,定義行爲 var handler = { set(target,prop,value,receiver) {//攔截set行爲 if(prop == 'name') { throw Error('不能夠哦') //這裏自定義你的邏輯,也能夠alert等。 } Reflect.set(target,prop,value,receiver) //不要忘了對其他屬性'放行' } } var p1 = new Proxy(new Person('張三'),handler) console.log(p1.name) //張三 p1.name = '李四' //Error:不能夠哦 p1.buy('貓糧'); p1.buy('貓砂'); console.log(p1.count) //2 //若是須要從'內部'修改p1的名字,則須要先對被代理對象進行定義 var _p1 = new Person('張三'); var p1 = new Proxy(_p1,handler) console.log(p1.name); //張三 _p1.name = '李四'; console.log(p1.name) //李四
以上我對這道題的理解。至於爲何不用class的setter,是由於這樣寫後,在new Person的時候不能傳name進去,由於一傳進去就會被攔截。因此只能先初始化對name賦值,再進行proxy代理對name攔截。
var Person = function(name,count=0) { var things = [],name = name result = { count = count; }; result.__proto__ = { buy:function(something) { things.push(something); result.count = things.length; }, getName:function() { // 經過getName函數來獲取名字 return name; } } return result; } var p2 = Person('王五'); p2.getName() //王五 p2.name = 123; p2.getName() //王五 p2.buy('妙鮮包'); console.log(p2.count) // 1
兩種方法見仁見智,第二種野路子不用Proxy代理,返回的是Object對象,而第一種正規軍則返回Person對象,更符合題意。
寫到這不知道你們發現了沒。 其實第一種方法也能夠不須要proxy代理,再init
函數中定義name = this.name,再在Person原型上寫一個getName
函數,這樣2種方法的優勢就結合到一塊兒了Σ(っ °Д °;)っ
這2小時沒有白花,這文章沒有白寫,又賺到了^ ^。
但願能給你們帶來一點點收穫,若是有不一樣的見解能夠留言一塊兒探討()。
Thanks for reading