Cap*_*ara 5 javascript canvas ecmascript-6
我想创建一个扩展的新类CanvasRenderingContext2D。这样我就可以将用户定义的属性分配给prototype该新类的属性,而不是分配给CanvasRenderingContext2D.attribute. 以下是我打算写的代码:
class WL_CRC2D extends CanvasRenderingContext2D{
constructor(){
super();
}
setStyle(args){//...
}
//...
}
var ctx = new WL_CRC2D() // Uncaught TypeError: Illegal constructor
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为CanvasRenderingContext2D会阻止new操作符 - 正如以下代码也会引发错误:
var ctx = new CanvasRenderingContext2D(); // Uncaught TypeError: Illegal constructor
Run Code Online (Sandbox Code Playgroud)
然后我尝试用另一种方式重写构造函数:
class WL_CRC2D{
constructor(){
let ctxTemp = Object.create(CanvasRenderingContext2D.prototype);
for (let i of Reflect.ownKeys(ctxTemp.__proto__)){
Object.defineProperty(this.__proto__, i, Object.getOwnPropertyDescriptor(ctxTemp.__proto__, i));
}
}
setStyle(args){//...
}
//...
}
var ctx = new WL_CRC2D(); // fine
console.log(ctx.arc); // function arc() { [native code] }
ctx.arc(0, 0, 10, 0, 1, true); // Uncaught TypeError: Illegal invocation
Run Code Online (Sandbox Code Playgroud)
正如注释所示,以WL_CRC2D这种方式创建的新实例实际上无法访问WL_CRC2D.prototype.
那么有没有一种方法可以避免污染系统定义的类CanvasRenderingContext2D呢?请指教。谢谢!
我可能以一种丑陋的方式解决了这个问题:
class WL_CanvasRenderingContext2D{
constructor(ctx){
this.ctx = ctx;
}
}
(() => {
var context = document.createElement('canvas').getContext('2d');
for (let i of Reflect.ownKeys(Object.getPrototypeOf(ctx))){
if (['symbol', 'constructor'].indexOf(typeof i) < 0){
var propertyDesc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(context), i);
if (typeof context[i] != 'function'){
[propertyDesc.get, propertyDesc.set] = [function(){return this.ctx[i]}, function(val){this.ctx[i] = val;}];
}
else{
propertyDesc.value = function(...args) {this.ctx[i].apply(this.ctx, args)};
}
Object.defineProperty(WL_CanvasRenderingContext2D.prototype, i, propertyDesc);
}
}
})();
var a = new WL_CanvasRenderingContext2D(ctx);
Run Code Online (Sandbox Code Playgroud)
如果上面的代码有任何缺陷,请仍然通知我。谢谢!