【问题标题】:Why I need JavaScript prototype in extending object?为什么我需要 JavaScript 原型来扩展对象?
【发布时间】:2018-03-20 14:02:29
【问题描述】:

很长时间以来,我使用 jQuery、ReactJS 和 NodeJS 服务器端 (ExpressJS) 用 Ja​​vaScript 编写代码。我学习了部分 MDN 和其他资源,但是有一个问题我找不到答案。
为什么跟随代码需要prototype 对象的属性?为什么我不能直接从Array 对象使用forEach?我的意思是,就OOP而言,如果Array类扩展类包含forEach方法,我可以直接从Array实例化的对象中调用它,我不需要,使用反射找到基类,实例化它并调用来自基类的方法。

Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
    el.addEventListener('click', someFunction);
});

示例取自这里:https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/

【问题讨论】:

  • 旧版浏览器在 DOM 元素上没有 forEach,事实上我认为 IE11 甚至在 DOM 元素上都没有 forEach .. ps。 DOM 元素不是数组..
  • querySelectorAll 不返回数组。它返回一个类似数组的对象,一个 NodeList。
  • 如果我使用数组作为call 的第一个参数,我可以省略prototype?
  • 否 - call 的第一个参数必须是您希望迭代的节点集。
  • 不要打扰那个代码,它已经过时了。你今天会写for (const el of document.querySelectorAll('.klasses')) el.addEventListener('click', someFunction);

标签: javascript oop


【解决方案1】:

您的代码:

Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){
    el.addEventListener('click', someFunction);
});

确实可以写成

[].forEach.call(document.querySelectorAll('.klasses'), function(el){
    el.addEventListener('click', someFunction);
});

遍历 Array 原型对象只是一种无需实际创建数组即可访问任何数组实例可用的函数的方法。使用一个或另一个主要是一个偏好问题,虽然第二种形式确实涉及创建一个数组对象,但对性能的影响很小。

【讨论】:

  • 创建一个新数组?严重吗?
  • @Ele 我不明白你的问题; [] 创建一个新数组,是的,如果这就是您的要求。\
  • 现代 JavaScript 运行时完全有可能跳过该数组的实例化,或者至少是可以想象的。
  • 是的,创建一个新数组只是为了访问该函数并不是一个好习惯。
  • 所以,正如我所见,prototype 我类似于以静态方式访问方法或实例化对象并访问它的方法。好的,谢谢。
【解决方案2】:

为什么我不能直接从 Array 对象中使用 forEach?

Array 对象是用于创建数组的构造函数。它没有自己的 forEach 属性。

您可以从 Array 的实例访问 forEach 属性(您可以使用 new Array 或者更惯用的方式使用 [] 创建),或者通过访问应用于实例的 prototype数组。

【讨论】:

  • 实际上似乎确实如此,至少在 Firefox 中是这样。 Array.forEach 给出“函数 forEach()”。并不是说它似乎可用; Array.forEach.call(['a'], function(g) { alert(g); }); 错误。
  • @Utkanos Those are deprecated,它们可以用作Array.forEach(['a'], function(g) { alert(g); });
  • 啊哈,有趣。谢谢。
【解决方案3】:

querySelectorAll 不返回数组,而是返回 NodeList(如数组对象)。 NodeList 有一个名为.length 的属性,它指示其中的元素数。

某些浏览器/引擎/后端技术不兼容,因为NodeList 不一定会提供forEach 的功能。

因此,另一种方法是使用 Array 原型将 NodeList 转换为 Array:

Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){...})

或者,您可以使用函数Array.from 将使用属性.length 创建数组:

Array.from(document.querySelectorAll('.klasses'));

来自 MDN 文档

虽然 NodeList 不是数组,但可以使用 forEach() 对其进行迭代。一些较旧的浏览器尚未实现此方法。您也可以使用Array.from 将其转换为数组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    相关资源
    最近更新 更多