创建实例,不带' new '操作符,参数列表可变

Create instance without `new` operator with variable argument list

本文关键字:列表 参数 new 实例 创建 不带 操作符      更新时间:2023-09-26

我想创建一个Point的实例,有和没有new操作符,如:

Point(5, 10); // returns { x: 5, y: 10 }
// or
new Point(5, 10); // also returns { x: 5, y: 10 }

在StackOverflow的帮助下,我让它工作到目前为止。

function Point() {
  if (!(this instanceof Point)) {
    var args = Array.prototype.slice.call(arguments);
    // bring in the context, needed for apply
    args.unshift(null);
    return new (Point.bind.apply(Point, args));
  }
  // determine X and Y values
  var pos = XY(Array.prototype.slice.call(arguments));
  this.x = pos.x;
  this.y = pos.y;
}

但这看起来很可怕,我甚至不将null转移到数组中,所以我可以使用apply。这感觉不太对。

我找到了很多解决方案,如何用新的构造函数和构造函数包装器来实现它,但我想保持它尽可能简单(它只是一个简单的点)。

是否有更简单的方法来实现这个行为?

如果你不介意使用ECMAScript 5函数,Object.create()可以帮助你:

function Point()
{   var args = Array.prototype.slice.call(arguments);
    if (this instanceof Point) return Point.apply(null, args);
    var pos = XY(args); 
    var result = Object.create(Point.prototype);
    result.x = pos.x;
    result.y = pos.y;
    return result;
}

如果你需要ECMAScript 3的兼容性,这个疯狂的、令人费解的解决方案是另一个选择(注意,它只是一个内部等价的new Point的包装器):

function Point() 
{   var pos = XY(Array.prototype.slice.call(arguments));
    function internalPoint()
    {   this.x = pos.x;
        this.y = pos.y;
    }
    internalPoint.prototype = Point.prototype;
    return new internalPoint;
}