如何使用JavaScript';s新运算符是否定义为函数?

如何使用JavaScript';s新运算符是否定义为函数?,javascript,Javascript,如果JavaScriptnew操作符是一个函数,它将如何定义 function _new(fn) { // What goes here? } 仇恨者会憎恨的,但像这样的事情 显然,这只是new的一个循环别名,但可以通过参数扩展它的潜力 由于用户代码的功能,有一些限制:本机构造函数,如newdate和newregexp和绑定函数,无法使用此函数正确填充 如果您正在查找相关的规范部分,它们是和 不管怎样,下面是: // we're assuming that correct argum

如果JavaScript
new
操作符是一个函数,它将如何定义

function _new(fn) {
    // What goes here?
}

仇恨者会憎恨的,但像这样的事情

显然,这只是
new
的一个循环别名,但可以通过参数扩展它的潜力


由于用户代码的功能,有一些限制:本机构造函数,如
newdate
newregexp
和绑定函数,无法使用此函数正确填充

如果您正在查找相关的规范部分,它们是和

不管怎样,下面是:

// we're assuming that correct arguments are given
function _new(F, args) {
  // we could have host objects, make sure edge case not left out
  // (typeof could be other than object or function in this case - see bottom)
  function Type(arg) {
    if (arg === undefined) return 'Undefined';
    if (arg === null) return 'Null';
    if (arg === false || arg === true) return 'Boolean';

    var type = typeof arg;
    if (type === 'string') return 'String';
    if (type === 'number') return 'Number';
    return 'Object';
  }

  // 1. Let obj be a newly created native ECMAScript object.
  // 2. Set all the internal methods of obj as specified in 8.12.
  // 3. Set the [[Class]] internal property of obj to "Object".
  // 4. Set the [[Extensible]] internal property of obj to true.
  // All of the steps above are implicitly completed in steps 6 or 7
  var obj;

  // 5. Let proto be the value of calling the [[Get]] internal property of F
  //    with argument "prototype".
  var proto = F.prototype;

  // 6. If Type(proto) is Object, set the [[Prototype]] internal property of
  //    obj to proto.
  if (Type(proto) === 'Object') obj = Object.create(proto);

  // 7. If Type(proto) is not Object, set the [[Prototype]] internal property
  //    of obj to the standard built-in Object prototype object as described
  //    in 15.2.4.
  else obj = {};

  // 8. Let result be the result of calling the [[Call]] internal property of
  //    F, providing obj as the this value and providing the argument list
  //    passed into [[Construct]] as args.
  var result = F.apply(obj, args);

  // 9. If Type(result) is Object then return result.
  if (Type(result) === 'Object') return result;

  // 10. Return obj.
  return obj;
}
关于
typeof
案例,即当宿主对象返回一个
typeof
值时的边缘案例,该值不是
object
function
。通过测试它们不可能是的任何东西,这允许我们正确地测试它,而不是依赖它们作为本机对象


请注意,这至少适用于ES5——填充
对象的唯一方法。在ES3或更旧的环境中创建
将使用我们当前正试图模拟的东西,这会破坏这样做的目的。

这似乎是最低限度的必要条件,尽管不是100%符合语言定义,也没有错误检查。只有ES5。
对象有一个垫片。create
,但它必须调用
new
,这在上下文中是毫无意义的

function _new(T, args) {
    var o = Object.create(T.prototype);
    var res = o.constructor.apply(o, args);
    return (typeof res === 'object') ? res : o;
}
使用方法:

function A(name) {
    this.name = name;
}

A.prototype.hello = function() {
    console.log(this);
}


var foo = _new(A, ['foo']);
var bar = _new(A, ['bar']);

console.log(foo.name);
console.log(bar.name);
调用构造函数的返回值测试是必要的,因为构造函数不必
返回此
——如果构造函数不返回任何内容,则
是隐式的


最近也有同样的好奇心

有些步骤是内部任务,无法在语言中重新实现

而且,在我的文章中,澳航在使用
typeof
作为仿
Type()

但是,有了这些,这是我能做到的最接近的了。尽管如此,它仍然需要可用(因此,ES5+)

例如:

function Foo(one, two) {
    this.one = one;
    this.two = two;
}

var bar = Object.new(Foo, 'a', 'b');

console.log(bar instanceof Foo); // true
console.log(bar.one);            // "a"
console.log(bar.two);            // "b"

以及注释版本,包括和中的步骤:


@raam86不,是接线员!这实际上是一个很好的问题……这个问题离题了,因为它不实用。
new
运算符是该语言的一部分。使用它。没有理由重新实现它。@RaymondChen我不同意-这个问题的答案可能也间接地回答了我自己的问题,关于如何使用一系列参数调用
new
。唉,这个问题是个骗局:Quantas 94 Heavy,Johathan Lonowski,阿尔尼塔克毫不费力地理解了我问题的含义,并给出了很好的答案。这个问题很简单,也很简洁,但更重要的是,已经有人这样问过了。如果你不喜欢这个问题,那么把它标记为一个傻瓜,而不是把它搁置。不是一个仇恨者,不是仇恨者,但这只是一个我知道即将到来的包装器(编辑时间==评论时间)。显然,我们需要一个更详细的答案。不过,我不是一个失败者,所以我不讨厌;)如果
prototype
未定义,那么它将无法按照规范工作。@qantas94h是的,这就是我所说的“最低限度的必要性”。但是,要创建一个没有原型的函数非常困难,您必须调用
对象。create(null)
,AFAICR.
res?res:o
不符合标准,但概念很接近。@Alnitak,不,实际上,还有很多细微差别,例如,在
函数a(){return 1};var b=新的A()
b
将是一个对象,而不是值
1
@zzzzBov啊,是的-因此它将是一个
类型的
测试,然后:(无论如何,我说过这是最小可能的-我没有尝试使其100%符合ES规范+1,以链接到行为的文档。
Object.new = function (constructor /*, args */) {
  function isObject(operand) {
    // detect and refuse primitives
    var type = typeof operand;
    return type !== 'undefined' &&
           type !== 'boolean' &&
           type !== 'number' &&
           type !== 'string' &&
           operand !== null;
  }

  var argList = Array.prototype.slice.call(arguments, 1);

  if (typeof constructor !== 'function') {
    throw new TypeError((typeof constructor) + ' is not a function');
  }

  var proto = constructor.prototype;
  var obj = Object.create(isObject(proto) ? proto : Object.prototype);

  var result = constructor.apply(obj, argList);
  return isObject(result) ? result : obj;
};
function Foo(one, two) {
    this.one = one;
    this.two = two;
}

var bar = Object.new(Foo, 'a', 'b');

console.log(bar instanceof Foo); // true
console.log(bar.one);            // "a"
console.log(bar.two);            // "b"
//    1. Let ref be the result of evaluating MemberExpression.
//    2. Let constructor be GetValue(ref).
Object.new = function (constructor /*, args */) {
  function isObject(operand) {
    // detect and refuse primitives
    var type = typeof operand;
    return type !== 'undefined' &&
           type !== 'boolean' &&
           type !== 'number' &&
           type !== 'string' &&
           operand !== null;
  }

  //  3. Let argList be the result of evaluating Arguments, producing an internal list of argument values (11.2.4).
  var argList = Array.prototype.slice.call(arguments, 1);

  //  4. If Type(constructor) is not Object, throw a TypeError exception.
  //  5. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
  if (typeof constructor !== 'function') {
    throw new TypeError((typeof constructor) + ' is not a function');
  }

  //  6. Return the result of calling the [[Construct]] internal method on constructor, providing the list argList as the argument values.

  //    For [[Construct]], it gets a bit out of order with current options for internal vs. abstractions.

  //    5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
  var proto = constructor.prototype;

  //    1. Let obj be a newly created native ECMAScript object.
  //    2. Set all the internal methods of obj as specified in 8.12.
  //    3. Set the [[Class]] internal property of obj to "Object".
  //    4. Set the [[Extensible]] internal property of obj to true.
  //
  //    6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
  //    7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
  var obj = Object.create(isObject(proto) ? proto : Object.prototype);

  //    8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
  var result = constructor.apply(obj, argList);

  //    9. If Type(result) is Object then return result.
  //   10. Return obj.
  return isObject(result) ? result : obj;
};