【问题标题】:What values can a constructor return to avoid returning this?构造函数可以返回什么值来避免返回 this?
【发布时间】:2010-12-30 23:40:58
【问题描述】:

当使用 new 关键字调用构造函数时,JavaScript 中的 return 语句可以返回 this 以外的值的确切情况是什么?

例子:

function Foo () {
  return something;
}

var foo = new Foo ();

如果我没记错的话,如果something 是一个非函数原语,this 将被返回。否则返回something。这是正确的吗?

换句话说,something 可以采用什么值来导致(new Foo () instanceof Foo) === false

【问题讨论】:

标签: javascript constructor new-operator


【解决方案1】:

[[Construct]] 内部属性描述了确切的条件,new 运算符使用该属性:

来自 ECMA-262 3rd。版本规范:

13.2.2[[Construct]]

Function 对象F[[Construct]] 属性为 调用,采取以下步骤:

  1. 创建一个新的原生 ECMAScript 对象。
  2. Result(1)[[Class]]属性设置为"Object"
  3. 获取F的原型属性值。
  4. 如果Result(3)是一个对象,则将Result(1)[[Prototype]]属性设置为Result(3)
  5. 如果Result(3)不是对象,则将Result(1)[[Prototype]]属性设置为原始Object原型对象为 在15.2.3.1 中描述。
  6. 调用F[[Call]] 属性,提供Result(1) 作为this 值和 提供传递给[[Construct]] 的参数列表作为 参数值。
  7. 如果@987654328@(Result(6))Object 然后返回Result(6)
  8. 返回Result(1)

看第 7 步和第 8 步,新对象只有在 Result(6) 的类型(从 F 构造函数返回的值 函数)是不是一个对象。

【讨论】:

  • 附加说明:typeof(null) 是“object”,但是返回 null not 会触发第 7 步发生
  • @BT:在我的 node.js 安装上进行测试,上面引用的规范中的“Type(x) is Object”表示“x instanceof Object is true”,不是typeof(x) === 'object'true”。例如,null instanceof Object 的计算结果为 false(实际上你不能从构造函数返回 null),new String("asdf") instanceof Object 的计算结果为 true(实际上你可以从构造函数返回一个字符串......)
  • @JoSo 我认为 Type 是指对象的内部 [[Class]] 属性。我们从 JavaScript 中获得的该值的最佳代理是 Object.prototype.toString.call(x)
  • @JoSo: 不。这意味着x 不是原始值,而是一个对象(包括数组、函数等)。它确实与typeofinstanceof 无关。
  • @Martian2049,因为null值的内部类型是Null Type,在内部,你可能认为这是“对象”,因为typeof null == 'object',但这不是内部类型操作检测到。它将返回在步骤 1 中创建的对象,因为在内部,nullinternal type 是 Null,而不是 Object。
【解决方案2】:

试着用更简单的语言表达几点。

在 javascript 中,当您在函数上使用 new 关键字时,如果,

  1. 函数不返回任何东西,它会返回一个预期的对象

function User() {
  this.name = 'Virat'
}

var user = new User();
console.log(user.name); //=> 'Virat'
  1. 函数返回任何真实复杂对象[对象、数组、函数等],该复杂对象优先,user 变量将保存返回的复杂对象

function User() {
  this.name = 'Virat';
  return function(){};
}

var user = new User();
console.log(user.name); //=> undefined
console.log(user); //=> function
  1. 函数返回任何字面量,构造函数优先,它会返回一个预期的对象

function User() {
  this.name = 'Virat';
  return 10;
}

var user = new User();
console.log(user.name); //=> 'Virat'

【讨论】:

    【解决方案3】:

    具体例子 http://jsbin.com/zivivucahi/1/edit?html,js,console,output

    /*
    ECMA 262 v 5
    http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
    "4.3.2
    primitive value
    member of one of the types Undefined, Null, Boolean, Number, Symbol, or String as defined in clause 6"
    */
    
    var Person = function(x){
      return x;
    
    };
    
    
    console.log(Person.constructor);
    console.log(Person.prototype.constructor);
    console.log(typeof(Person));
    console.log(typeof(Person.prototype));
    
    function log(x){
      console.log(x instanceof Person);
      console.log(typeof x);
      console.log(typeof x.prototype);
    }
    
    log(new Person(undefined));
    log(new Person(null));
    log(new Person(true));
    log(new Person(2));
    log(new Person(""));
    
    //returns a function not an object
    log(new Person(function(){}));
    
    
    //implementation?
    //log(new Person(Symbol('%')));
    

    【讨论】:

    • 很好的例子! lll
    • 只需添加:new Person({"stuff":"stuff"}) // {"stuff":"stuff"}
    【解决方案4】:

    附带说明,返回值或this 只是等式的一部分。

    例如,考虑一下:

    function Two() { return new Number(2); }
    var two = new Two;
    two + 2; // 4
    two.valueOf = function() { return 3; }
    two + 2; // 5
    two.valueOf = function() { return '2'; }
    two + 2; // '22'
    

    如您所见,.valueOf() 是内部使用的,可以被利用以获取乐趣和利润。您甚至可以创建副作用,例如:

    function AutoIncrementingNumber(start) {
        var n = new Number, val = start || 0;
        n.valueOf = function() { return val++; };
        return n;
    }
    var auto = new AutoIncrementingNumber(42);
    auto + 1; // 43
    auto + 1; // 44
    auto + 1; // 45
    

    我可以想象这一定有一些的实际应用。而且它也不必是明确的Number,如果您将.valueOf 添加到任何对象,它可以表现为一个数字:

    ({valueOf: function() { return Math.random(); }}) + 1; // 1.6451723610516638
    

    例如,您可以利用它来创建一个始终返回新 GUID 的对象。

    【讨论】:

      【解决方案5】:

      我找不到有关此事的任何文档,但我认为您是正确的。例如,您可以从构造函数返回 new Number(5),但不能返回文字 5(将被忽略并返回 this)。

      【讨论】:

      • 顺便说一句:这是因为new Number(5)(或者甚至只是Number(5),因为如果作为函数调用,它的工作原理是一样的)创建了一个数字对象 i>,例如这意味着 '' == false, !!new String('') == true.
      • 两年后准备回复以纠正我自己的评论,这行得通:function One(){return new Number(1)} 但这不行:function One(){return Number(1)}
      【解决方案6】:

      当您使用new 关键字时,会创建一个对象。然后调用函数初始化对象。

      函数无法阻止对象被创建,因为这是在调用函数之前完成的。

      【讨论】:

      • 我不接受。我知道你可以做我声称的事情(我已经尝试过了),但我不知道它发生的确切案例。在我的示例中,有可能以 (foo instanceof Foo) === false 结尾。
      • 为什么投反对票?如果你不解释你认为错的地方是什么,就无法改进答案。
      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多