JavaScript:如何实现Object,使新的Object({})和Object({})相同

时间:2018-04-06 17:00:08

标签: javascript object

在JavaScript中,我可以写:

x = new Object({ a: 3 })

我将x = { a: 3 }

同样,我可以写

x = Object({ a: 3 })

我将再次x = { a: 3 }

我的问题是:Object如何实现以满足这两种调用方式?在第一个场景中,它将收到一个新的this,而在第二个场景中它将收到全局对象。

我最好的猜测是:

var Object = function(obj) {
    var global = (function() { return this; })();
    if (global == this) { // I am called as a regular function
        // Create a copy of obj, potentially like this
        return { ...obj };
    } else { // I am called via new
        // Copy all fields of obj onto this
        // not sure what the best way to do this is.
    }
}

3 个答案:

答案 0 :(得分:4)

答案是in the specificaton

  

使用可选参数 value 调用 Object 函数时,将执行以下步骤:

     
      
  1. 如果NewTarget既不是未定义也不是活动函数,那么      
        
    • 回来? OrdinaryCreateFromConstructor(NewTarget,“%ObjectPrototype%”)。
    •   
  2.   
  3. 如果值 null 未定义或未提供,请返回ObjectCreate(%ObjectPrototype%)。
  4.   
  5. 回归! ToObject()。
  6.   

步骤#1是关于代码在创建从Object继承的内容的一部分时应该执行的操作,因此我们可以忽略该问题的步骤。

第2步不适用,因为您传递了value而且它既不是null也不是undefined

所以步骤#3会发生:它使用ToObject操作进行类型转换,将value转换为对象。由于value已经是一个对象,这是一个无操作,结果与您传入的对象相同。new Object new Object({a: 1})部分完全没必要。

  

在第一个场景中,它将收到一个新的this,而在第二个场景中,它将收到全局对象。

从上面的规范步骤中可以看出,Object根本不使用this

答案 1 :(得分:-1)

这很简单

function Object(obj) {
  return obj;
}

当您将其作为函数调用时,它会继承其父window的作用域。 在将其初始化为类时购买,函数本身就是具有自己的范围this的构造函数。

并且它不会创建具有复制属性的新实例,如您在此示例中所示:

var a = {a : 3};
var b = new Object(a);
var c = Object(a);

console.log(a === b);
console.log(a === c);

正如@ user2357112指出的那样,这不是那么简单,它更接近于Object功能:

function Object(value) {
  if (typeof value === 'number') {
    return new Number(value);
  }
  
  if (typeof value === 'string') {
    return new String(value);
  }
  
  if (value === null || value === undefined) {
    return {};
  } 
  
  return value
}

var a = new Object(undefined);

console.log(new Object(1));
console.log(new Object('sad'));
console.log(new Object([]));
console.log(new Object({}));
console.log(new Object(null));
console.log(new Object());

答案 2 :(得分:-1)

我认为它类似于

2018-01-02 23:00:00 -> 2018-01-01 23:00:00
2018-04-04 10:00:00 -> 2018-04-01 10:00:00