如何在Javascript中使用new调用的构造函数返回null?

时间:2011-12-23 17:04:42

标签: javascript

我正在尝试使构造函数在某些内容失败时中止对象构造,例如它无法获取画布。

但是当我使用new时,我发现klass()始终返回this,无论是否返回null或任何其他值,我可以解决此问题以返回null吗?

现在我想到,一个解决方案可能是在klass()中创建新实例并返回该实例或null,而不是使用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 );

6 个答案:

答案 0 :(得分:12)

更好的解决方案是抛出错误:

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?  ;-)

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

答案 1 :(得分:12)

您可以改为使用“工厂功能”或“静态工厂方法”:

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();

使用较新的类语法相同:

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

答案 2 :(得分:3)

您可以使用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

答案 3 :(得分:0)

答案很遗憾,你不能:(。原因在于答案:

What values can a constructor return to avoid returning this?

答案 4 :(得分: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' );

答案 5 :(得分:0)

我遇到了同样的问题:

  ...
  function MyConstructor () 
  { ...
    let Null = { valueOf: ()=>null }
    return Null;
  } 

构造函数不能返回null。但它可以返回任何Object,因此它可以返回上面定义的对象'Null'。然后,构造函数的调用者只需在使用结果之前调用valueOf():

let maybeNull = (new MyConstructor (maybeArg)) . valueOf();

这是有效的,因为valueOf()是一个内置的JavaScript方法 默认情况下,除了盒装数字之外的所有内容 盒装字符串和盒装布尔回归自己。

您可以覆盖任何对象的valueOf(),就像我上面所做的那样 对于我的Null(),返回null。