7

我正在尝试创建一个Proxy对象Image捕获属性,但即使使用空处理程序,我也会收到一条错误消息。

TypeError:Node.appendChild 的参数 1 没有实现接口 Node。

代理对象应该充当目标对象,所以这让我有点困惑。据我了解,您也应该能够使用DOM 节点执行此操作(?)。

另外:我无法开始加载图像并在设置属性onload时触发处理程序。src

我应该如何使用代理,以便我可以“接管”例如“src”属性,否则让它像普通图像对象一样工作?

我的代码

'use strict';

//--- normal image use ---
var imgNormal = new Image();
imgNormal.onload = function(){
  console.log('Normal loaded OK');
  document.body.appendChild(imgNormal);
};
imgNormal.src = 'https://i.imgur.com/zn7O7QWb.jpg';

//--- proxy image ---
var imgProxy = new Proxy(Image, { // I also tried with 'new Image()' and HTMLImageElement
  set: function(a,b,c,d){
    console.log('set '+b);
    return Reflect.set(a,b,c,d);
  }
});
imgProxy.onload = function(){
  console.log('Proxy loaded OK');
  document.body.appendChild(imgProxy);
};
imgProxy.src = 'https://i.imgur.com/zn7O7QWb.jpg';

document.body.appendChild(imgProxy); // double-up to demo error

更新:感谢@Harangue!使用 " new" (bah..) 确实使代理对象变得栩栩如生,但是现在我无法捕获属性的设置。它似乎完全忽略了陷阱-例如:

var proxy = new Proxy(Image, {
      set: function(a,b,c,d){
        console.log('set '+b);        // doesn't show
        return Reflect.set(a,b,c,d);
      }
    });

    var imgProxy = new proxy();
    imgProxy.onload = function(){
      console.log('Proxy loaded OK');
      document.body.appendChild(imgProxy);
    };
    imgProxy.src = 'https://i.imgur.com/zn7O7QWb.jpg';

如何使用有效代理捕获属性设置?

更新 2另一方面 -new代理一起使用似乎只使用原始构造函数。我能找到的所有例子都没有使用新的:

var myProxy = new Proxy(.., ..);  // should suffer

在此之上使用 thennew myProxy()似乎只使用原始构造函数,这不是我想要的,因为它忽略了陷阱。

var proxy = new Proxy(Image, {}); //should be sufficent??
var proxy2 = new proxy();
console.log(proxy2); //-> says Image (not proxy..)

陷阱似乎在我的第一次尝试中起作用,但代理的行为不如预期。这太令人困惑了,太新奇了。对如何解决这两个问题(陷阱和行为)的任何输入感到高兴。

4

2 回答 2

4

new永远不要低估关键字的重要性。;)

//--- proxy image ---
var imgProxy = new Proxy(Image, {  // I also tried with 'new Image()'
  set: function(a,b,c,d){
    console.log('set '+b);
    return Reflect.set(a,b,c,d);
  }
});
imgProxy.src = 'https://i.imgur.com/zn7O7QWb.jpg';

document.body.appendChild(new imgProxy); // double-up to demo error

使用代理,您可以有效地扩展 Image 对象。但是发送 Image 构造函数本身,而不是它返回的 DOM Node,确实会缺少所需的appendChild.

于 2016-08-06T08:45:14.033 回答
1

作为代理的替代方案,您还可以覆盖对象本身的属性,从而控制其行为:

function findDescriptor(obj, prop){
    if(obj != null){
        return Object.hasOwnProperty.call(obj, prop)?
            Object.getOwnPropertyDescriptor(obj, prop):
            findDescriptor(Object.getPrototypeOf(obj), prop);
    }
}

var img = new Image();
var {get, set} = findDescriptor(img, "src");

Object.defineProperty(img, "src", {
    configurable: true,
    enumerable: true,

    //get: get,  //keep behaviour
    get(){       //overwrite getter
        var v = get.call(this);  //call the original getter
        console.log("get src:", v, this);
        return v;
    },

    //same for setter
    set(v){
        console.log("set src:", v, this);
        //modify value before applying it to the default setter
        v = v.toLowerCase();
        set.call(this, v);
    }
});

img.src = "FileWithUppercaseLetters.jpg"; //setter
img.src;  //trigger getter

并且由于这个属性是在Image.prototype* 上定义的,你可以简单地扩展这个类并修改继承类的原型上的行为

*至少在FF中,必须检查其他浏览器

于 2016-08-06T09:17:29.037 回答