React:在哪里扩展对象原型 [英] React: Where To Extend Object Prototype

查看:107
本文介绍了React:在哪里扩展对象原型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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. For example:

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

(您可能需要查看这个问题以了解有关扩展对象原型的更多信息。)

(You may want to take a look at this question to learn more about extending object prototypes.)

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

Yes I can define it beside a component and use it within. But what is the best and cleanest way?

我应该把它写成类方法还是在<$ c里面$ c> componentDidMount 还是别的什么?

Should I write it as a class method or inside componentDidMount or something else?

编辑:

在React(或JavaScript)中扩展对象原型是否OK?

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

推荐答案

TLDR答案:无处!



- 细致的答案 -


我正在尝试做的是扩展纯JavaScript类,比如String类,这是javascript中非常常见的任务。

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

甚至是OK在React(或JavaScript)中扩展对象原型?

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

在JavaScript中扩展/修改原生原型是有争议的主题,与你所说的相反,不是最重要的专业开发人员经常这样做。 普遍共识扩展本机JS原型是一种编程反模式避免,因为它打破了封装原则并修改了全局状态。但是,与许多规则一样,可能会有罕见的例外情况。例如:你正在开发一个不需要生产质量的玩具项目,你是唯一一个接触过该代码库的开发者,或者你的代码永远不会成为其他任何人的依赖。

Extending/modifying native prototypes in JavaScript is a controversial topic, and, contrary to what you said, not something most professional developers do very often. The general consensus is that extending the native JS prototypes is a programming anti-pattern to be avoided, because it breaks the principle of encapsulation and modifies global state. However, as with many rules, there may be rare exceptions to it. For instance: you're working on a toy project that doesn't need to be production quality, you're the only dev who will ever touch that code base, or your code will never be a dependency for anyone else.

如果您有充分的理由并且真正了解自己在做什么,并且充分了解修改运行时本机数据类型/行为的潜在后果环境和依赖关系,那么也许你会发现这种做法的一些有效用例。但很可能不是,或者至少不是经常。几乎从来没有。

If you have a really good reason and really know what you're doing and are fully aware of the potential consequences of your modifications to the native data types/behaviors for your run-time environment and dependencies, then perhaps you will find some valid use case for this practice. But most likely not, or at least not very often. Like almost never.

如果你只是在方便/语法糖之后,你最好不要使用实用功能(来自lodash,underscore或ramda等)并学习实践功能组合。但是如果你真的致力于面向对象的范式,那么你应该只是子类化原生数据类型而不是修改它们

If you're just after convenience / syntactic sugar, you're better off pulling in utility functions (from the likes of lodash, underscore, or ramda) and learning to practice functional composition. But if you're really committed to the Object Oriented paradigm, then you should probably just be "subclassing" the native data types rather than modifying them.

所以不要像这样改变一个类的原型:

So rather than mutating a class's prototype like this:

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类语法),如下所示:

You would create a sub-class (only works with ES6 class syntax), like so:

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一样工作,当然除了你不能写像字符串文字这样的MyString文字。

This subclass would work like a built-in String in every way, except of course that you wouldn't be able to write MyString literals like String literals.


我使用create-react-app创建了一个纯React应用程序。我想扩展String类并在一个或多个组件中使用它...是的我可以在组件旁边定义它并在其中使用它。但最好和最干净的方法是什么? ...我应该把它写成类方法还是在componentDidMount或其他内容?

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?

因为修改内置原型(通过变异)诸如 String.prototype 之类的东西会改变你的应用程序的全局状态,你只想执行一次,几乎可以肯定在任何其他代码执行之前(因为你'重新设置字符串对于之后执行的所有代码的行为的全局状态。因此,在React组件实例方法中更改内置原型并没有多大意义。

Because modifying built-in prototypes (by mutating things like String.prototype) alters the global state of your application, it is something that you will want to execute only once and almost certainly before any other code executes (because you're setting the global state of how Strings behave for all code that executes after). So altering built-in prototypes from within a React component instance method wouldn't make much sense.

如果您要做脏事,我建议为您要修改的每个本机类型创建一个单独的模块,并将这些模块保存在某处,如 src / lib / extend-built-ins / 或其他东西,然后 import 它们是<$中的第一件事C $ C>的src / index.js 。你不需要出口任何东西。执行 import src / lib / extend-built-ins / String.js 将执行代码,这将改变您的全局状态。这将提供至少合适的组织,并确保在应用程序的其余代码运行之前完全修改您的应用程序环境。这样你就可以在整个应用程序中使用扩展类型,而无需考虑从某个地方导入它们。

If you're going to do the dirty deed, I'd recommend creating a separate module for each native type you want to modify, and keep those modules somewhere like src/lib/extend-built-ins/ or something, and then import them as the very first thing in src/index.js. You wouldn't need to export anything. Doing import src/lib/extend-built-ins/String.js will execute the code, which will mutate your global state. That would provide at least decent organization and ensure that your application environment is fully modified before the rest of your app's code runs. That way you can just use your extended types throughout your application without thinking about importing them from somewhere.

如果你要去子类化路径(类MyThing扩展了NativeThing ),然后我建议你在不同的模块中类似地定义你的自定义类,比如 src / lib / native-subclasses / 。但在这种情况下,你必须你的类构造函数导入到你想要使用它们的任何/每个模块中。

If you're going to go the subclassing route (class MyThing extends NativeThing), then I would recommend you similarly define your custom classes in separate modules somewhere like src/lib/native-subclasses/. But in this case, you would have to import your class constructors into any/every module where you want to use them.

但是,如果您想开发干净,可测试,可重构的代码,这些代码对其他人和您未来的自我都很容易理解,那么您就不应该这样做。相反,考虑采用React及其生态系统的函数式编程原理。任何人都可以快速阅读和理解纯函数,因此使用它们来完成数据和状态转换,而不是依赖于修改全局对象等难以跟踪的黑客攻击。理解这一个小黑客可能是可爱而微不足道的,但在项目中甚至一次这样做可以促进和鼓励自己和他人使用额外的快捷方式和反模式。

However, if you want to develop clean, testable, refactorable code that will be easy for others and your future self to understand, you shouldn't do this sort of thing. Instead, think about adopting the functional programming principles of React and its ecosystem. Anyone can quickly read and understand a pure function, so use them to accomplish your data and state transformations rather than relying on hard-to-track hacks like modifying global objects. It may be cute and trivial to understand this one little hack, but doing it even once in a project promotes and encourages yourself and others to use additional shortcuts and anti-patterns.

这篇关于React:在哪里扩展对象原型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆