重新定义的 toString 的 getOwnPropertyDescriptor 应该是未定义的

Posted

技术标签:

【中文标题】重新定义的 toString 的 getOwnPropertyDescriptor 应该是未定义的【英文标题】:getOwnPropertyDescriptor of redefined toString should be undefined 【发布时间】:2020-07-11 18:28:08 【问题描述】:

我重新定义了toStringhtmlCanvasElement.prototype.toDataURL。当我得到toString 的属性描述符时,它应该返回undefined,但它会返回函数。任何想法如何解决它?

你可以在这里执行代码https://jsfiddle.net/nqk50a8r/

Object.defineProperty(HTMLCanvasElement.prototype.toDataURL, 'toString', 
    value: function ()  return 'function toDataURL()  [native code] ';
);

var desc = Object.getOwnPropertyDescriptor(HTMLCanvasElement.prototype.toDataURL, 'toString');

console.log(desc === undefined);

如果您删除了defineProperty 块,您将看到它返回undefined

我用下一个代码重新定义了toDataURL

Object.defineProperty(HTMLCanvasElement.prototype, 'toDataURL', 
    value: function ()  return 'new valu' 
);

如果我没有重新定义toString,它会在调用toString 时自行返回代码。

【问题讨论】:

为什么应该是undefined?每个自己的属性都有一个描述符。 @CertainPerformance 如果删除 defineProperty 块,您将看到它返回 undefined。所以很容易追踪到 toString 被重新定义了。 如果您要添加一个以前不存在的属性,则无法从想要检查它的代码中隐藏它 - 他们可以看到描述符 但是属性存在,如果你执行HTMLCanvasElement.prototype.toDataURL.toString()它会返回你的值。也许我以不正确的方式重新定义了属性? 是的,属性存在,所以描述符是not undefined 【参考方案1】:

HTMLCanvasElement.prototype.toDataURL 默认没有自己的 属性toString。通过引用HTMLCanvasElement.prototype.toDataURL.toString 获得的toString 方法原型继承自Function.prototype.toString

console.log(
  HTMLCanvasElement.prototype.toDataURL.toString === Function.prototype.toString
);

HTMLCanvasElement.prototype.toDataURL.toString 上不存在直接属性。但如果你自己添加一个,通过

Object.defineProperty(HTMLCanvasElement.prototype.toDataURL, 'toString',

那么它拥有这样一个自己的属性,并且如果你检查它也会记录一个属性描述符。

如果您想在保持HTMLCanvasElement.prototype.toDataURL.toString 为空的同时对自定义toString 方法进行monkeypatch,您可以覆盖Function.prototype.toString

请注意,虽然这在技术上是可行的,但这样做也很奇怪,而且改变内置原型也是一个坏主意:

const origToString = Function.prototype.toString;
Function.prototype.toString = function() 
  if (this === HTMLCanvasElement.prototype.toDataURL) return 'function toDataURL()  [native code] ';
  else return origToString.call(this);

【讨论】:

以上是关于重新定义的 toString 的 getOwnPropertyDescriptor 应该是未定义的的主要内容,如果未能解决你的问题,请参考以下文章

java CharSequence接口

当使用书架的withRelated得到“无法读取未定义的属性'toString'”

如何修复“TypeError:无法读取未定义的属性 'toString'” |不和谐.js

Js toString()方法笔记

Sequelize 迁移失败,无法读取未定义的属性“toString”[关闭]

Struts2 调试标签认为 toString() 未定义