oop 类中定义 的函数_函数式编程与javascript中的oop

oop 类中定义 的函数

What is the difference between OOP and functional programming? To figure this out we will be writing a small factorial website calculator. The first approach uses functional programming, the second one OOP.

OOP和函数式编程之间有什么区别? 为了弄清楚这一点,我们将编写一个小的阶乘网站计算器。 第一种方法使用函数式编程,第二种方法使用OOP。

介绍 (Introduction)

Before we get started with coding I want to give you a quick introduction to object-oriented and functional programming.

在开始编码之前,我想向您简要介绍一下面向对象和函数式编程。

Both are programming paradigms differing in the techniques they allow and forbid.

两者都是编程范式,不同之处在于它们允许和禁止的技术。

There are programming languages that only support one paradigm e.g. Haskell (purely functional).

有些编程语言仅支持一种范例,例如Haskell (纯功能)。

As well as languages that support multiple paradigms such as JavaScript, you can use JavaScript to write object-oriented or functional code or even a mixture of both.

除了支持多种范例的语言(如JavaScript)外 ,您还可以使用JavaScript编写面向对象的代码或功能代码,甚至可以同时编写二者。

建立 (Setup)

Before we can dive deep into the differences between these two paradigms we need to set up the project.

在深入探究这两种范例之间的差异之前,我们需要设置项目。

For that we first create all the files and folders we need like this:

为此,我们首先创建需要的所有文件和文件夹,如下所示:

$ mkdir func-vs-oop
$ cd ./func-vs-oop
$ cat index.html
$ cat functional.js
$ cat oop.js

I’m using the cat command because it works both on Linux-systems and Windows Powershell.

我使用cat命令是因为它在Linux系统和Windows Powershell上都可以使用。

Next up we need to create a simple form for the factorial calculator inside the index.html.

接下来,我们需要在index.html中为析因计算器创建一个简单的表单。

index.html
index.html

To give this form a better look and feel we use bootstrap as a CSS-Framework. If you display this HTML in the browser it should look like this:

为了使这种外观更好,我们将bootstrap用作CSS-Framework 。 如果在浏览器中显示此HTML,则它应如下所示:

Image for post
factorial calculator
阶乘计算器

Currently, this form won’t do anything.

目前,此表单不会执行任何操作。

Our goal is to implement a logic where you can enter a number up to 100. After clicking the “Calculate”-button it should show the result in the result-div. We will implement this both in the object-oriented way and the functional way.

我们的目标是实现一种逻辑,在该逻辑中,您可以输入一个最大为100的数字。单击“计算”按钮后,应在result-div中显示结果。 我们将以面向对象的方式和功能的方式来实现。

功能实现 (Functional implementation)

First off we will create a file for the functional programming approach.

首先,我们将为功能编程方法创建一个文件。

$ cat functional.js

To get started we need a function that gets called when loading this file into the browser. This function should get the form and then add the functionality we need to the submit-event of the form.

首先,我们需要一个在将此文件加载到浏览器时调用的函数。 该函数应获取表单,然后将我们需要的功能添加到表单的提交事件中。

function addSubmitHandler(tag, handler) {
const form = getElement(tag);
form.addEventListener('submit', handler);
}addSubmitHandler('#factorial-form', factorialHandler);

First, we declare the function called addSubmitHandler.

首先,我们声明一个名为addSubmitHandler的函数。

This function takes in two parameters, the first one being the tag we want to look for in our HTML, the second one being the function we want to bind to the submit-event of our Element.

这个函数有两个参数,第一个是我们要在HTML中查找的标签,第二个是我们要绑定到Element的commit-event的函数。

Next, we call this function by passing in #factorial-form and the function name factorialHandler. The hashtag in front of the tag indicates that we are looking for the id-attribute in the HTML.

接下来,我们通过传入#factorial-form和函数名称factorialHandler来调用此函数。 标签前面的#标签表明我们正在寻找HTML中的id属性。

This code will throw an error if you try to run it now because neither the function getElement nor factorialHandler is defined anywhere.

如果您现在尝试运行该代码,则会抛出错误,因为在任何地方都未定义函数getElementfactorialHandler

So let’s first define getElement above our addSubmitHandler function like this:

因此,让我们首先在addSubmitHandler函数上方定义 getElement ,如下所示:

function getElement(tag) {
return document.querySelector(tag);
}

This function is really simple and only returns the HTML-Element we found by the tag we passed in.

此函数非常简单,仅返回通过传入的标记找到HTML元素。

But we will reuse this function later on.

但是稍后我们将重用此功能。

Now let’s start creating the core logic by adding the factorialHandler function above the addSubmitHandler.

现在,通过在addSubmitHandler上方添加factorialHandler函数来开始创建核心逻辑。

function factorialHandler(event) {
event.preventDefault();
const inputNumber = getValueFromElement('#factorial');
try {
const result = calculateFactorial(inputNumber);
displayResult(result);
} catch (error) {
alert(error.message);
}
}

We pass in the event and instantly call preventDefault. This will prevent the default behavior of the submit event, you can try out what happens on the button click without calling preventDefault.

我们传递事件并立即调用preventDefault 。 这将防止提交事件的默认行为,您可以尝试单击按钮时发生的情况,而无需调用preventDefault

After that, we get the value entered by the user from the input-field by calling the getValueFromElement function. Upon getting the number we try to calculate the factorial by using the function calculateFactorial and then render the result to the page by passing the result to the function displayResult.

之后,我们通过调用getValueFromElement函数从输入字段中获得用户输入的值。 得到数字后,我们尝试使用函数calculateFactorial计算阶乘,然后通过将结果传递给函数displayResult将结果呈现到页面。

If the value is not in the correct format or the number is higher than 100, we will throw an error and display that as an alert. This is the reason for using a try-catch-block in this particular case.

如果该值的格式不正确或数字大于100,我们将抛出错误并将其显示为警报。 这就是在这种特殊情况下使用try-catch-block的原因。

In the next step, we create two more helper functions, getValueFromElement, and displayResult. Let’s add them below the getElement function.

在下一步中,我们将再创建两个帮助器函数getValueFromElementdisplayResult 。 让我们将它们添加到getElement函数下方。

function getValueFromElement(tag) {
return getElement(tag).value;
}function displayResult(result) {
getElement('#factorial-result').innerHTML = result;
}

Both of these functions use our getElement function. This reusability is one part of why functional programming is so effective.

这两个函数都使用我们的getElement函数。 这种可重用性是功能编程如此有效的原因之一。

To make this even more reusable we could potentially add a second argument to displayResult, called tag. So that we can dynamically set the element that should display the result. But in this example, I went with the hard-coded way.

为了使其更可重用,我们可以在displayResult上添加第二个参数,称为tag。 这样我们就可以动态设置应该显示结果的元素。 但是在此示例中,我采用了硬编码方式。

Next up we create our calculateFactorial function right above factorialHandler.

接下来,我们在factorialHandler上方创建我们的calculateFactorial函数。

function calculateFactorial(number) {
if (validate(number, REQUIRED) && validate(number, MAX_LENGTH, 100) && validate(number, IS_TYPE, 'number')) {
return factorial(number);
} else {
throw new Error('Invalid input — either the number is to big or it is not a number');
}
}

We validate if the argument ‘number’ is not empty, not above 100, and of type number. For that, we use a function called validate that we will need to create next. If the checks pass we call the function factorial and return its result. If these checks don’t pass we throw the error we caught in the factorialHandler function.

我们验证参数'number'是否为空,且不大于100,并且类型为number。 为此,我们使用了一个称为validate的函数,接下来将需要创建它。 如果检查通过,我们将调用函数阶乘并返回其结果。 如果这些检查没有通过,我们将抛出在factorialHandler函数中捕获的错误。

First let’s create the validate function right below displayResult and the three constants MAX_LENGTH, IS_TYPE, and REQUIRED.

首先,让我们在displayResult和三个常量MAX_LENGTH,IS_TYPE和REQUIRED下创建validate函数。

const MAX_LENGTH = 'MAX_LENGTH';
const IS_TYPE = 'IS_TYPE';
const REQUIRED = 'REQUIRED';function validate(value, flag, compareValue) {
switch (flag) {
case REQUIRED:
return value.trim().length > 0;
case MAX_LENGTH:
return value <= compareValue;
case IS_TYPE:
if (compareValue === 'number') {
return !isNaN(value);
} else if (compareValue === 'string') {
return isNaN(value);
}
default:
break;
}
}

In this function, we use a switch to determine which kind of validation we are going to perform. After determining that, it is just a simple value validation.

在此功能中,我们使用开关来确定要执行的验证类型。 确定后,这只是一个简单的值验证。

Now we are going to add the actual factorial function right above the calculateFactorial declaration. This will be our last function for this approach.

现在,我们将在calculateFactorial声明的上方添加实际的阶乘函数。 这将是此方法的最后功能。

function factorial(number) {
let returnValue = 1;
for (let i = 2; i <= number; i++) {
returnValue = returnValue * i;
}
return returnValue;
}

There are many different ways to perform a factorial calculation, I went with the iterative approach.

执行迭代方法有很多不同的方法来执行阶乘计算。

If you want to learn more about the different approaches I recommend you check out this article on GeeksForGeeks: https://www.geeksforgeeks.org/program-for-factorial-of-a-number/

如果您想了解有关不同方法的更多信息,我建议您在GeeksForGeeks上查看以下文章: https ://www.geeksforgeeks.org/program-for-factorial-of-a-number/

The final functional.js file should look like this:

最终的functional.js文件应如下所示:

functional.js
Functional.js

In this approach, we worked exclusively with functions. Every function got a single purpose and most of them are reusable in other parts of the application.

在这种方法中,我们专门处理功能。 每个功能都有一个目的,大多数功能可以在应用程序的其他部分中重用。

For this simple web application, the functional approach is a bit of an overkill. Next, we will code the same functionality but this time object-oriented.

对于这个简单的Web应用程序,功能方法有些过头了。 接下来,我们将编写相同的功能,但这次是面向对象的。

面向对象的实现 (Object-oriented implementation)

First of all, we need to change the src in the script-tag of our index.html file to the following.

首先,我们需要将index.html文件的script-tag中的src更改为以下内容。

<script src=”oop.js” defer></script>

Now we create the oop.js file.

现在,我们创建oop.js文件。

$ cat oop.js

For the OOP approach, we want to create three different classes, one for validation, one for the factorial calculation, and one for handling the form.

对于OOP方法,我们要创建三个不同的类,一个用于验证,一个用于阶乘计算,一个用于处理表单。

We get started with creating the class that handles the form.

我们开始创建处理表单的类。

InputForm
输入表格

In the constructor, we get the form-element and the input-element and store it in class variables, also called properties. After that, we add the method factorialHandler to the submit-event. In this case, we need to bind ‘this’ of the class to the method.

在构造函数中,我们获取form-element和input-element并将其存储在类变量(也称为属性)中。 之后,我们将方法factorialHandler添加到Submit -event。 在这种情况下,我们需要将类的 “ this” 绑定到方法。

If we don’t do that we will get reference errors, e.g. calling this.numberInput.value will be undefined. After that, we create the class method factorialHandler with the event as an argument.

如果不这样做,将会得到引用错误,例如,调用this.numberInput.value将是未定义的。 之后,我们以事件为参数创建类方法factorialHandler

The code of this method should look somewhat familiar, for example, the if-statement checks if the input value is valid or not as we did in the calculateFactorial function.

该方法的代码看起来应该有点熟悉,例如,if语句像在calculateFactorial函数中一样检查输入值是否有效。

Validator.validate is a call to a static method inside the class Validator that we still need to create. We don’t need to initialize a new instance of an object if we work with static methods. After the validations pass we create a new instance of the Factorial class, pass in the input value and then display the calculated result to the user.

Validator.validate是对我们仍然需要创建的Validator类中的静态方法的调用。 如果使用静态方法,则无需初始化对象的新实例。 验证通过后,我们将创建一个新的Factorial类实例,传入输入值,然后将计算结果显示给用户。

Next up we are going to create the Validator class right above the InputForm class.

接下来,我们将在InputForm类上方创建Validator

Validator
验证器

As you can see everything inside of this class is static, the method validate as well as the three properties. Therefore we do not need any constructor. The advantage of this is that we do not need to initialize this class every time we want to use it.

正如你可以看到这个类里面的一切是静态的,方法验证以及三个属性。 因此,我们不需要任何构造函数。 这样做的好处是,我们不需要每次使用它时都初始化该类。

validate is mostly the same as the validate function is our functional.js except that we do this.REQUIRED, this.MAX_LENGTH and this.IS_TYPE*instead of just the variable name.

validate与我们的functional.jsvalidate函数基本相同,除了我们执行this.REQUIREDthis.MAX_LENGTHthis.IS_TYPE *而不只是变量名。

Next up we create our Factorial class right below the Validator class.

接下来,我们在Validator类的下面创建我们的Factorial

Factorial
阶乘

Upon initializing an instance of this class we get the resultElement and store it as a property as well as the number we pass in. After that, we call the method calculate and store it’s return value in a property. The calculate method contains the same code as the factorial function in functional.js. Last but not least we got the display method that sets the innerHTML of our resultElement to the calculated factorial number.

在初始化这个类的一个实例,我们得到的resultElement并将其存储为一个属性,以及我们在经过数。在那之后,我们所说的方法计算 ,它的返回值存储在一个属性。 该计算方法包含相同的代码作为functional.js 阶乘函数。 最后但并非最不重要的一点是,我们获得了一种显示方法,该方法将resultElementinnerHTML设置为计算出的阶乘数。

The complete oop.js file should look like this.

完整的oop.js文件应如下所示。

oop.js
oop.js

We created three different classes handling three different aspects of our application:

我们创建了三个不同的类来处理应用程序的三个不同方面:

- Validation: Validation class

-验证: 验证类别

- Factorial Handling: Factorial class

-析取处理: 析取类

- Form Handling: InputForm class

-表单处理: InputForm类

结论 (Conclusion)

Both approaches are valid ways of structuring your code. I like to try out what works best in the different projects I work on. Most of the time it is not even possible to separate both paradigms so clearly.

两种方法都是构造代码的有效方法。 我喜欢尝试在我从事的不同项目中最有效的方法。 在大多数情况下,甚至不可能如此清晰地分离这两种范式。

I hope this little comparison gave you a fundamental understanding of what the different approaches look like.

我希望这个小的比较可以使您对不同方法的外观有一个基本的了解。

As always you can find the code for this project on my GitHub.

与往常一样,您可以在我的GitHub上找到该项目的代码。

翻译自: https://levelup.gitconnected.com/functional-programming-vs-oop-in-javascript-539202768406

oop 类中定义 的函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值