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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8618722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 04:00:16  来源:igfitidea点击:

How to return null from a constructor called with new in Javascript?

javascript

提问by Petruza

I'm trying to make the constructor abort the object construction if something fails, for example it can't get a hold of a canvas.

如果出现故障,我试图让构造函数中止对象构造,例如它无法获得画布。

But as I'm using newI see that klass() always returns thisregardless of any return null or any other value, can I work around this to return null?

但是当我使用时,new我看到 klass() 总是返回this而不管任何返回 null 或任何其他值,我可以解决这个问题以返回 null 吗?

Now that I think of, a solution may be to create the new instance inside klass() and return that instance or null, and not use new, is there a better solution?

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

回答by Linus Kleen

The better solution would be to throw an error:

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

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
}


EDIT:Constructors can be "forced" to not return an instance:

编辑:可以“强制”构造函数不返回实例:

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

The odd thing is, however, that if a "constructor" returns a number, string, true, false, etc., it actually doesreturn an instance. The second solution only works when the constructor returns an empty array []or an empty object {}.

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

回答by Kos

You could make a "factory function" or "static factory method" instead:

您可以改为创建“工厂函数”或“静态工厂方法”:

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

Same thing using the newer class syntax:

同样的事情使用较新的类语法:

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

回答by georg

You can use combine a factory with the constructor in one function using the technique described in John Resig's article. Example:

您可以使用John Resig 的文章 中描述的技术将工厂与构造函数结合在一个函数中 。例子:

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

回答by B T

The answer is unfortunately, you can't : ( . The reasons are in this answer:

不幸的是,答案是,你不能 :( 。原因在这个答案中:

What values can a constructor return to avoid returning this?

构造函数可以返回哪些值来避免返回 this?

回答by headacheCoder

As I posted in my comment above...

正如我在上面的评论中发布的那样......

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

回答by Panu Logic

I got around the same problem with this trick:

我用这个技巧解决了同样的问题:

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

A constructor can not return null. But it can return any Object so it can return the object 'Null' defined above. The caller of the constructor then simply needs to call valueOf() before using the result:

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

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

This works because valueOf() is a built-in JavaScript method which by default for everything except boxed Numbers boxed Strings and boxed Booleans returns themselves.

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

You can override valueOf() for any object, like I did above for my Null(), to return null.

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