2011-12-23 73 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'); 
相關問題