2016-04-22 39 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