将 Intl.DateTimeFormat 理解为 JavaScript 对象

Understanding Intl.DateTimeFormat as a JavaScript object

我不理解 Intl.DateTimeFormat 的行为。

它没有公开我期望 JavaScript 对象的行为。 我想明白为什么?

以下代码片段演示了无法覆盖 DateTimeFormat 上的 format 方法。这怎么可能?

const itDateTimeFormat1 = new window.Intl.DateTimeFormat('it-CH');
const originalFormat = itDateTimeFormat1.format;
itDateTimeFormat1.format = function(date){ return 'Overriden! ' + originalFormat(date)};
console.log(itDateTimeFormat1.format(new Date())); // -> 13/7/2017

也似乎不可能通过原型继承从 DateTimeFormat 派生。以下代码段会引发错误:

const itDateTimeFormat2 = new window.Intl.DateTimeFormat('it-CH');
const wrappedDateTimeFormat = Object.create(itDateTimeFormat2);
wrappedDateTimeFormat.format = function(date){ return 'Overriden! ' };
console.log(wrappedDateTimeFormat.format(new Date()));
// Firefox:
// TypeError: Intl.DateTimeFormat.prototype.format called on value that's not an object initialized as a DateTimeFormat
// Chrome:
// Uncaught TypeError: Method format called on incompatible receiver #<DateTimeFormat>

为什么 DateTimeFormat 不像 "normal" JavaScript 对象?

DateTimeFormat如何防止覆盖方法?

DateTimeFormat 如何防止覆盖派生对象?

原回答

好吧,因为它是一个内置对象 - 最好将其冻结。 但是你可以在 Javascript 和 Object.defineProperty.

中做这样的事情

看下面的截图。您可以使用 writeable: false 防止覆盖您的属性。 (我用过 JS 5.1)

var MyCoolConstructor = function () {

  Object.defineProperty(this, 'nonWriteable', {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function () {return 42;}
  });
};

var instance = new MyCoolConstructor();


console.log(instance.nonWriteable()); //42
instance.nonWriteable = function () {return 'overriden';}
console.log(instance.nonWriteable()); //42

如何防止原型继承?

检查这个简单的片段。您可以只检查当前上下文是否与您的构造函数具有相同的原型。

var MyCoolConstructor = function () {
  this.foo = function () {
    if (Object.getPrototypeOf(this) === MyCoolConstructor.prototype) {
      return 42;
    } else {
      throw new Error('bad this');
    }
  };
};

var instance = new MyCoolConstructor();
console.log(instance.foo());
//42

var instance2 = Object.create(instance);
console.log(instance2.foo())
//Bad this

编辑 2

派生对象的方法覆盖也可以用同样的方式来防止, 他们导出 属性 配置。 检查这个片段,它是前 2

的组合
var MyCoolConstructor = function () {
  Object.defineProperty(this, 'foo', {
    value: function () {
      if (Object.getPrototypeOf(this) === MyCoolConstructor.prototype) {
        return 42;
      } else {
        throw new Error('bad this');
      }
    },
    writeable: false
  });
};

var instance = new MyCoolConstructor();
console.log(instance.foo());
//42

var derivedInstance = Object.create(instance);
derivedInstance.foo = function () {
  return 'overriden';
};
console.log(derivedInstance.foo());
//Bad this. Can't be overridden because foo property is not writeable

在 3..2..1..

如果你真的想覆盖 smth,Object.defineProperty 来拯救。

const itDateTimeFormat2 = new window.Intl.DateTimeFormat('it-CH');
const wrappedDateTimeFormat = Object.create(itDateTimeFormat2);
Object.defineProperty(wrappedDateTimeFormat, 'format', {value: function(date) { return 'Overridden!' + date.toString(); }})
wrappedDateTimeFormat.format()
//"Overriden! ..."

结论

正如我们在示例中看到的那样。系统对象的行为就像正常配置的 javascript 对象