javascript - react : Where To Extend Object Prototype

标签 javascript reactjs prototype create-react-app

我使用 create-react-app 创建了一个纯 React 应用程序.我想扩展 String类并在一个或多个组件中使用它。例如:

String.prototype.someFunction = function () {
    //some code
}

(您可能想查看 this question 以了解有关扩展对象原型(prototype)的更多信息。)

是的,我可以在组件旁边定义它并在其中使用它。但是最好和最干净的方法是什么?

我应该把它写成 class method或在 componentDidMount 内或者是其他东西?

编辑:

在 React(或 JavaScript)中扩展对象原型(prototype)甚至“可以”吗?

最佳答案

TLDR 答案:无处!
-- 细致入微的答案 --

What I'm trying to do is extend pure JavaScript classes, like String class, which is a very common task in javascript

Is it even "OK" to extend object prototype in React (or in JavaScript) at all?


在 JavaScript 中扩展/修改原生原型(prototype)是 controversial topic ,而且,与你所说的相反,大多数专业开发人员不经常这样做。 general consensusextending the native JS prototypes is a programming anti-pattern to be avoided ,因为它打破了封装原则,修改了全局状态。但是,与许多规则一样,它可能很少有异常(exception)。例如:您正在开发一个不需要生产质量的玩具项目,您是唯一会接触该代码库的开发人员,或者您的代码永远不会成为其他任何人的依赖项。
如果你有一个很好的理由并且真的知道你在做什么,并且完全意识到你对运行时环境和依赖项的 native 数据类型/行为的修改的潜在后果,那么也许你会发现一些有效的用途这种做法的案例。但很可能不会,或者至少不会很频繁。几乎从来没有。
如果你只是追求便利/语法糖,你最好引入实用函数(来自 lodash、underscore 或 ramda 之类的函数)并学习练习函数组合。但如果你真的致力于面向对象的范式,那么 您可能应该只是将 native 数据类型“子类化”而不是修改它们 .
所以不要像这样改变一个类的原型(prototype):

String.prototype.somethingStupid = function () {
  return [].map.call(this, function(letter) {
    if ((Math.random() * 1) > .5) return letter.toUpperCase()
    else return letter.toLowerCase()
  }).join('')
}

console.log('This is a silly string'.somethingStupid())

您将创建一个子类(仅适用于 ES6 类语法),如下所示:

class MyString extends String {
  constructor(x = '') {
    super(x)
    this.otherInstanceProp = ':)'
  }
  
  somethingStupid() {
    return [].map.call(this, function(letter) {
      if ((Math.random() * 1) > .5) return letter.toUpperCase()
      else return letter.toLowerCase()
    }).join('')
  }
}

const myStr = new MyString('This is a silly string')
console.log(myStr)
console.log(myStr.valueOf())
console.log(myStr.somethingStupid() + ', don\'t you think?')

这个子类在各个方面都像一个内置的 String 一样工作,当然你不能像 String 字面量那样编写 MyString 字面量。

I created a pure React application using create-react-app. I would like to extend the String class and use it in one or more components ... Yes I can define it beside a component and use it within. But what is the best and cleanest way? ... Should I write it as a class method or inside componentDidMount or something else?


因为修改内置原型(prototype)(通过改变 String.prototype 之类的东西)会改变应用程序的全局状态,所以您只需执行一次并且几乎可以肯定在任何其他代码执行之前执行它(因为您正在设置全局之后执行的所有代码的字符串行为状态)。因此,从 React 组件实例方法中更改内置原型(prototype)没有多大意义。
如果你打算做坏事,我建议为你想修改的每个原生类型创建一个单独的模块,并将这些模块保存在 src/lib/extend-built-ins/ 之类的地方。什么的,然后import他们是 src/index.js 中的第一件事.你不需要导出任何东西。做import src/lib/extend-built-ins/String.js将执行代码,这将改变你的全局状态。这将提供至少体面的组织,并确保在应用程序的其余代码运行之前完全修改您的应用程序环境。这样您就可以在整个应用程序中使用您的扩展类型,而无需考虑从某个地方导入它们。
如果您要走子类化路线( class MyThing extends NativeThing ),那么我建议您在单独的模块中类似地定义自定义类,例如 src/lib/native-subclasses/ .但在这种情况下,您必须 import您的类构造函数到您要使用它们的任何/每个模块中。
但是,如果你想开发干净、可测试、可重构的代码,让其他人和你 future 的自己容易理解,你不应该做这种事情。相反,考虑采用 React 及其生态系统的函数式编程原则。任何人都可以快速阅读和理解纯函数,因此请使用它们来完成您的数据和状态转换,而不是依赖于难以跟踪的技巧,例如修改全局对象。理解这个小技巧可能很可爱和微不足道,但即使在项目中这样做一次也会促进和鼓励你自己和其他人使用额外的快捷方式和反模式。

关于javascript - react : Where To Extend Object Prototype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47630632/

相关文章:

javascript - 在 JavaScript 中将对象引用作为函数参数传递

javascript - Remove() 在 mongodb 中不起作用?

javascript - 如何确定 jQuery 滚动事件的方向?

reactjs - Material-UI 版本 5 中的主题类型是什么?

Javascript:将方法添加到函数原型(prototype)

javascript - Getter/Setter 和原型(prototype)链

javascript - AngularJS 中的价格数据过滤器

JavaScript 模态框对于屏幕来说太大了

reactjs - 数据的部分渲染

reactjs - 如何将数据存储到从reactjs中的props接收到的const变量