Proxy object cannot be added to DOM (traps doesn't trigger either)

I am trying to make a Proxy object of Image to trap properties but even with an empty handler I get an error message.

TypeError: Argument 1 of Node.appendChild does not implement interface Node.

The proxy object is suppose to act as the target object so this baffles me a little. As far as I understand you should be able to do this with DOM nodes as well (?).

Also : I cannot start loading the image and have the onload handler triggered when setting the src property.

How should I use the Proxy so I can "take over" for example the "src" property and otherwise have it act like a regular image object?

My code

'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

Never underestimate the importance of the new keyword. ;)

//--- 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

With the proxy you effectively extend the Image object. But sending the Image constructor itself, rather than the DOM Node returned by it, would indeed be missing the needed appendChild .


As an alternative to a proxy you can also overwrite the property on the object itself and therefore control it's behaviour:

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

And since this property is defined on the Image.prototype *, you can simply extend this class and modify the behaviour on the prototype of the inherited Class

*at least in FF, have to check the other browsers

链接地址: http://www.djcxy.com/p/92792.html

上一篇: 我可以在.NET标准类库中使用动态吗?

下一篇: 代理对象不能添加到DOM(陷阱不会触发)