2

我不明白 的行为Intl.DateTimeFormat

它不会暴露我对 JavaScript 对象所期望的行为。我想明白为什么?

下面的代码片段演示了formatonDateTimeFormat方法不能被覆盖。这怎么可能?

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不像一个“正常”的 JavaScript 对象?

如何DateTimeFormat防止覆盖方法?

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

4

1 回答 1

2

原始答案

好吧,因为它是一个内置对象 - 最好将其冻结。但是你可以在 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

也可以以相同的方式防止派生对象方法覆盖,它们派生属性配置。检查这个片段,它是前两个的组合

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.. 中不是很酷的 hack

如果你真的想覆盖 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 对象一样

于 2017-07-13T10:13:18.890 回答