2011-12-23 72 views
8

我试图让构造函数中止对象构造,如果失败了,例如它不能获得一个画布。如何从Javascript中使用new调用的构造函数返回null?

但是,因为我使用new我看到klass()总是返回this,无论返回null或任何其他值,我可以解决此问题返回null吗?

现在我想到了,一种解决方案可能是在klass()内创建新实例并返回该实例或为空,而不是使用new,有没有更好的解决方案?

function klass(canvas_id) { 
    var canvas = document.getElementById(canvas_id); 

    if(! (canvas && canvas.getContext)) { 
     return null; 
    } 
} 
var instance = new klass('wrong_id'); 
console.log(instance, typeof instance); 
+1

你可以抛出一个异常,或者你可以在你的对象中设置一些可以测试的状态 – jfriend00 2011-12-23 17:07:15

回答

12

你可以做一个“工厂函数”或“静态工厂方法”,而不是:

class Foo { 
    static CreateFoo() { 
    if (something) { 
     return null; 
    } 
    return new Foo(); 
    } 
} 
+0

我认为这通常会是一种更好的方法。尝试抓取一个函数中的元素,如果找到了,将它传递给构造函数。如果不是,则返回null。 – 2011-12-23 17:16:38

10

更好的解决办法是抛出一个错误:

function klass(canvas_id) { 
    var canvas = document.getElementById(canvas_id); 

    if(! (canvas && canvas.getContext)) { 
     throw new Error('Not a canvas'); 
    } 
} 

// later... 

try { 
    var c = new klass("canvas_id"); 
} catch(E) { 
    // error caught 
} 

编辑:构造函数可以被 “强迫” 有来无回一个实例:

function Foo() { 
    var canvas = ...; 

    if ('undefined' == '' + Foo.CANVAS_CHECK) 
     Foo.CANVAS_CHECK = (canvas && canvas.getContext); 

    if (!Foo.CANVAS_CHECK) 
     return []; // the constructor will actually return an empty array 

    // passed; initialize instance here 
} 


// later on... 

var foo; 

if (!((foo = new Foo()) instanceof Foo)) { 
    // Failed. Canvas is unsupported. 
} 

// You happy now, am not i am? ;-) 

但奇怪的是,如果“构造函数”返回一个数字字符串,即true,false等,它实际上确实是返回一个实例。第二种解决方案仅在构造函数返回空数组[]或空对象{}时才起作用。

+1

你真的想用'try/catch'语句混淆你的代码来测试一个元素w如发现? – 2011-12-23 17:14:11

+1

不检查是否找到元素。但是如果你想验证canvas是否真的被支持,我宁愿抛出一个异常。 – 2011-12-23 17:23:01

+0

是的,这很好。尽管正如@amnotiam所说的,我希望能更好地使用像'if(!(a = new klass('id'))' – Petruza 2011-12-23 17:28:54

2

您可以使用一个工厂的结合:使用较新的类语法

Foo.CreateFoo = function() { 
    // not to confuse with Foo.prototype. ... 
    if (something) { 
    return null; 
    } 
    return new Foo(); 
}; 

// then instead of new Foo(): 
var obj = Foo.CreateFoo(); 

同样的事情构造函数使用John Resig's article中描述的技术。例如:

function Person(name) { 
    var me = arguments.callee; 

    if (!(this instanceof me)) { 
     // factory code 

     // validate parameters.... 
     if(!name.match(/^[a-z]+$/)) 
      return null; 

     // ...and call the constructor 
     return new me(arguments); 

    } else { 

     // constructor code 
     this.name = name;  

    } 
} 


a = Person("joe") // ok 
b = Person("bob") // ok 
c = Person("R2D2") // null 
+0

+1不仅仅是为了复制,而是在应有的地方给予奖励。 (可能也是最好的单线程,但。) – 2011-12-23 21:31:06

0

正如我张贴在我上面的评论...

function klass(canvas_id) { 
    var canvas = document.getElementById(canvas_id); 

    if(! (canvas && canvas.getContext)) { 
     return new Boolean; 
    } 
} 

var instance1 = new klass('wrong_id'); 

if(!(instance1 instanceof klass)) 
    console.log('Canvas is not suppored'); 

var instance2 = new klass('wrong_id').valueOf(); 

console.log(instance2, typeof instance2); 

if(instance2 !== false) 
    console.log('Canvas is supported, yeah'); 
相关问题