【问题标题】:JavaScript: Calling a prototype returns 'not a function' errorJavaScript:调用原型返回“不是函数”错误
【发布时间】:2019-11-13 08:08:01
【问题描述】:

我创建了一个简单的 ptotype 函数,我想用它来编辑我网页上元素的数据属性。我正在像从 49.0.2623.112m 到最新的每个版本的 chrome 一样对其进行测试。 关键是……它在任何地方都不起作用……

我无法让这段代码在我的项目中运行。它似乎在stackoverflow(低于sn-p)上运行良好,但它不适用于我在我的计算机上本地托管的任何项目。即使在只有 bodya 元素的空白页上,也没有任何额外的脚本。

每次我运行此代码时,它都会返回 ar 错误 ...is not a function

我的问题是: 它是由过时的浏览器的一些问题引起的,还是在编写时出错?我完全迷失在这里。我搜索了两天,没有找到答案..

<html>
<head>
<script>
Element.prototype.data = function(name, value) {
 this.setAttribute(name, value);
}
</script>
</head>

<body>
  <a href="#">Text</a>
</body>

<script type="text/javascript">
window.setTimeout(function(){ document.querySelector('a').data('href','https://google.com');
},5000);
</script>

</html>

【问题讨论】:

  • @Paulpro 如果这是问题所在,错误将是 Cannot read property 'data' of null
  • 原型是由位于所有body 内容之前的脚本创建的,但它会在所有内容完全加载后调用。控制台中的错误日志告诉原型存在但不是一个函数...
  • 不要使用堆栈片段,因为它不会像您指出的那样重现问题,您能否 edit 您的问题并提供一个最小的 HTML 文件作为 的代码块 本地运行时重现问题?
  • 在 Firefox 和 Chrome 最新版本中都非常适合我。顺便说一句,您所做的只是为setAttribute 创建一个别名。它将以完全相同的方式使用。比较 document.querySelector('a').data(k,v)document.querySelector('a').setAttribute(k,v)。哪一个不需要进一步调查就可以理解?哪一种容易与运行方式不同的jquery方法混淆?哪一个可能导致用户意外覆盖重要属性?还请考虑使用内置原型进行胡闹是不好的坏坏的......
  • 即当代码剪切'n'粘贴到本地文件时,对我来说非常有效......

标签: javascript syntax-error prototype


【解决方案1】:

如 cmets 中所述,monkey-patching prototypes is considered harmful。通过将属性用作数据存储,您可能会遇到您的方法覆盖重要的 HTML 属性的情况,并且您的数据只能是 string 类型。

通过使用WeakMap,您可以创建一个没有这些缺点的独立 函数,其中数据的生命周期仍然绑定到它“连接”到的元素的生命周期。

const data = (() => {
  const map = new WeakMap();
  return (element, key, value) => {
    if (value == null) {
      const innerMap = map.get(element);
      if (innerMap) {
        return innerMap.get(key);
      }
    }
    const innerMap = map.get(element) || new Map();
    map.set(element, innerMap);
    innerMap.set(key, value);
  };
})();

const el1 = document.querySelector("#el1");
const el2 = document.querySelector("#el2");
data(el1, "hello", "world");
data(el2, "foo", {
  complex: "object"
});
console.log(data(el1, "hello")); // "world"
console.log(data(el2, "hello")); // undefined
console.log(data(el2, "foo"));   // {complex: "object"}
<div id="el1">some element</div>
<div id="el2">some other element</div>

【讨论】:

  • 感谢您提供的所有信息。我找到了一种对我来说似乎是简单解决方案的方法。我刚刚创建了一个构造函数,它返回 selectod 对象(就像 Jquery 的 $ 一样)并将原型添加到该构造函数中......这样文档对象不会以任何方式改变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
  • 1970-01-01
  • 2020-05-09
相关资源
最近更新 更多