javascript – 无法从上下文对象继承?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – 无法从上下文对象继承?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5354字,纯文字阅读大概需要8分钟。
内容图文
![javascript – 无法从上下文对象继承?](/upload/InfoBanner/zyjiaocheng/786/154b1e5a54f54884934d1f2e02b201b7.jpg)
我试图创建一个继承自上下文对象的对象.但是在从我继承的对象调用函数时,浏览器(Chrome)会声明Uncaught TypeError:Illegal invocation.这是基本代码:
http://jsfiddle.net/adrianh/BKYfv/1/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ctx2 = Object.create(ctx);
ctx.setTransform(1, 0, 0, 1, 0, 0); // identity -- works
alert("ctx works");
ctx2.setTransform(.5, 0, 0, .5, 0, 0); // scale by half -- fails
alert("ctx2 works");
为什么这会失败?
解决方法
我写了一个makeForwardingObject()函数来完成我想要的.它可以在here找到.
// makeForwardingObject(obj, funcs, attribs)
//
// obj - the object that is being forwarded to
// funcs - array of non enumerable function member names to forward to
// attribs - array of non enumerable attributes to forward to
//
// Makes a forwarding object that forwards all functions calls and attribute
// requests to the forwarded object. In this way, the original object is
// acted upon directly, while you can delete or modify members to your
// object without interfering with the original.
//
// Access to the object being forwarded to is always available using member
// functions applyParent(), callParent(), setParentAttrib() and
// getParentAttrib().
//
// If funcs or attribs are enumerable in the object, they are not added
// a second time.
function makeForwardingObject(obj, funcs, attribs)
{
var _ = { };
Object.defineProperties(_, {
_: { value: obj },
// like obj.apply() except it applys to object being forwarded to.
applyParent : { value: function applyParent(func, args)
{
return this._[func].apply(this._, args);
}},
// like obj.call() except it applys to object being forwarded to.
callParent: { value: function callParent(func)
{
// FF at least doesn't understand arguments.slice(),
// arguments.splice() or arguments.shift(). WTF?!?!
var args=[];
for (i=1; i<arguments.length; ++i)
args[i-1]=arguments[i];
return this._[func].apply(this._, args);
}},
// this is for setting member of object being forwarded to.
setParentAttrib: { value: function setParentAttrib(attrib, val)
{
return this._[attrib]=val;
}},
// this is for getting member of object being forwarded to.
getParentAttrib: { value: function getParentAttrib(attrib, val)
{
return this._[attrib];
}},
});
for (var key in obj)
{
switch (typeof obj[key])
{
case 'function':
_[key] = eval("(function "+key+"() { return this._."+key+".apply(this._, arguments); })");
break;
default:
eval("Object.defineProperty(_, '"+key+"', {"+
"get: function "+key+"() { return this._."+key+"; },"+
"set: function "+key+"(v) { return this._."+key+"=v; },"+
"enumerable: true,"+
"})");
break;
}
}
for (var index in funcs)
{
var key = funcs[index];
if (!_.hasOwnProperty(key))
{
_[key] = eval("(function "+key+"() { return this._."+key+".apply(this._, arguments); })");
}
}
for (var index in attribs)
{
var key = funcs[index];
if (!_.hasOwnProperty(key))
{
eval("Object.defineProperty(_, '"+key+"', {"+
"get: function "+key+"() { return this._."+key+"; },"+
"set: function "+key+"(v) { return this._."+key+"=v; },"+
"enumerable: false,"+
"})");
}
}
return _;
}
// Return a string of all the members in an object. Used for debugging.
function getMembers(obj)
{
var _ = "";
for (key in obj)
{
_ += key + ":" + typeof obj[key] + " = " + obj[key] +"\n";
}
return _;
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var ctx2 = makeForwardingObject(ctx);
var x = { a: "" };
alert(getMembers(ctx));
alert(getMembers(ctx2));
ctx.setTransform(1, 0, 0, 1, 0, 0); // identity -- works
alert("ctx works");
ctx2.setTransform(.5, 0, 0, .5, 0, 0); // scale by half -- works!
//These are alternate ways to call the forwarded object's member functions:
// ctx2.applyParent('setTransform', [.5, 0, 0, .5, 0, 0]); // scale by half -- works!
// ctx2.callParent('setTransform', .5, 0, 0, .5, 0, 0); // scale by half -- works!
alert("ctx2 works");
ctx2.moveTo(0,0);
ctx2.lineTo(100, 100);
ctx2.stroke();
解决方法:
一个浅薄的答案是因为无法构造画布渲染上下文.使用CanvasRenderingContext2d()函数(就像DOM中的许多其他构造函数一样)将抛出一个Type错误:“非法构造函数”,因为它们应该只从工厂函数以特定的方式创建.在这种情况下,画布的.getContext()方法.
尽管使用RenderingContext2d作为原型创建了一个新对象,但您可以使用错误地创建渲染上下文
ctx2=Object.create(CanvasRenderingContext2D.prototype);
要么
ctx2=Object.create(ctx.constructor.prototype);
给你一个完全空白的无状态(和无用)渲染上下文对象,它实际上抛出与克隆上下文相同的异常.它甚至没有分配画布.
这不起作用的原因是因为你只继承了对RenderingContext原型的公共方法的引用,并且在你克隆的情况下引用了你通过原型链创建它的上下文的所有状态,但是除此之外它是一个空心的身体.在CanvasRenderingContext构造函数中声明的私有var和没有私有声明的函数都是通过原型继承的.
如果你很好奇,你可以自己写这种对象
function nonConstructable(factoryVar){
if(arguments.callee.caller !== Factory){
throw TypeError("Invalid constructor");
}
var privateVar = privateMethod();
privateVar+=factoryVar;
this.publicVar= privateVar;
function privateMethod(){
return 123;
}
}
function Factory(){
var privateFactoryVar = 321;
return new nonConstructable(privateFactoryVar );
}
您可以通过这种方式看到这两个对象是链接的,并且您在nonConstructable构造函数中执行操作的唯一方法是通过特定的Factory构建它.
做一些更多的研究似乎CanvasRenderingContext2D和WebGLRenderingContext被计划为上下文的有效构造函数,谁可以只渲染到任何画布,并且都应该在工作线程内工作.我无法弄清楚实施的当前状态是什么,似乎两年前由于某种原因人们完全停止写它.
内容总结
以上是互联网集市为您收集整理的javascript – 无法从上下文对象继承?全部内容,希望文章能够帮你解决javascript – 无法从上下文对象继承?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。