2016-04-22 54 views
0

考慮以下代碼:每當我叫app.mediaLibrary.media.push(new app.mediaLibrary.Media("", "")) 在控制檯使用代理與普通陣列

app.mediaLibrary = new function MediaLibrary() { 
    var self = this; 

    self.media = new Proxy([], { 
     set(target, key, value) { 
      console.log(`Setting value ${key} as ${value}`) 
      if (!(value instanceof self.Media)) 
       throw new Error(`${value} is not instance of Media.`) 
      target[key] = value; 
      return true 
     }, 
     get (target, key) { 
      console.log(`Getting value ${key} as ${target[key]}`) 
      return target[key] 
     } 
    }); 

    self.Media = function Media(file, fileReader) { 
     this.src = fileReader.result; 
     this.file = file; 
    } 

    return self; 
} 

我看到這一點:

Getting value push as function push() { [native code] } 
Getting value length as 0 
Setting value 0 as [object Object] 
Setting value length as 1 
Uncaught Error: 1 is not instance of Media.(…) 

我明白爲什麼我看到這一點,但我怎麼能圍繞它的代碼?看來我的陷阱是由內部觸發的(push,length)以及外部電話([0]=...),我不知道如何區分它們。有任何想法嗎?

+0

我不明白你的差異化方案。如果一個電話可以被視爲「外部」,那麼它肯定是「推」。它依次調用「get length」和「set 0」。那麼,什麼樣的資產可以作爲內部資源? – zeroflagL

+0

我沒有在我的代碼中調用get length,所以它是內部/隱式調用,而不是外部/顯式。 –

+0

根據這個定義,世界上每個圖書館都只包含內部電話。即使有人在回撥中調用您的代碼。這沒有什麼意義。 – zeroflagL

回答

1

我想你是在問錯誤的問題。這不是關於內部調用或外部調用,這是關於您正在代理的特定對象:數組。

您可以用三個條件去:

  1. 長度可任意設置(只有數組會處理這個反正)
  2. 數值屬性只能設置爲媒體實例。
  3. 所有其他屬性都是禁用的。

你可以寫這樣的:

app.mediaLibrary = new function MediaLibrary() { 
    var self = this; 

    self.media = new Proxy([], { 
     set(target, key, value) { 
      console.log(`Setting value ${key} as ${value}`) 

      // Check if this is a valid array index 
      // See http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects 
      if (String(key >>> 0) === key && (key >>> 0) != Math.pow(2, 32) - 1) { 
       if (!(value instanceof self.Media)) 
        throw new Error(`${value} is not instance of Media.`); 
      } else if(key !== 'length') { 
       throw new Error(`${key} may not be written to.`); 
      } 
      target[key] = value; 
      return true 
     }, 
     get (target, key) { 
      console.log(`Getting value ${key} as ${target[key]}`) 
      return target[key] 
     } 
    }); 

    self.Media = function Media(file, fileReader) { 
     this.src = fileReader.result; 
     this.file = file; 
    } 

    return self; 
} 

如果你真的需要.push[0]=...區分,那麼沒有,就不能完成。

+0

那麼,你可以通過裝飾getter中的返回函數來區分'.push()',但是我同意在檢查屬性名稱時沒有必要象你一樣。 – Bergi

+0

而不是使用'Number(key)== key',你可能想顯式檢查String(key >>> 0)=== key &&(key >>> 0)!= 4294967295' – Bergi

+0

@Bergi good與裝飾者的想法,謝謝。對於按位運算符,我有點不清楚,你會介意解釋你的第二部分('>>>'似乎做了類型轉換和舍入技巧)? 4294967295是最高可能的索引嗎? – nils