在JavaScript中显示OOP和过程编程之间差异的一个很好的例子是什么?

时间:2016-04-23 19:39:10

标签: javascript function oop object procedural-programming

我无法用JavaScript来了解OOP。

很多年前,我曾经涉足BASIC编程并在学校学习了一些COBOL和FORTRAN,所以我对程序编程有点熟悉,但我从来没有学到任何这些高水平的熟练程度或复杂性。我也用JS做了一些hackey事情,但我想这主要是程序性的而不是OOP。

最近,我决定培养自己成为一名网络开发人员并正确学习JavaScript,并根据好评如潮,我决定使用Head First JavaScript Programming作为我的教科书。

我遇到的问题是我无法弄清楚使用对象的方式和原因与使用函数和变量有什​​么不同或更好。我已经浏览了大量的教程和视频,但他们都说与本书完全相同。 "物体是有用的,因为它们类似于现实生活中的日常物品,例如汽车。汽车有型号年份,品牌,重量,颜色等......汽车也可以做一些事情,比如开始,停止,去等等。它们是对象内部的功能并被称为'方法&# 39;"然后是"这是如何创建一个对象:"

var myCar = {
    make: "Chevy";
    year: 2004;
    kilograms: 2000;
    color: "blue";
    go: function() {
        alert("go!");
    }
};

大。现在我知道对象在某种程度上类似于现实生活中的东西,我知道如何使用属性和方法制作对象。我知道了。

我可以通过调用它们来访问这些属性值:

a = myCar.make;
b = myCar.year;
c = myCar.color;

我也可以调用函数(或方法):

myCar.go();

奇妙。但我仍然无法弄清楚为什么我想这样做。为什么这比以下更好?

myCarMake = "Chevy";
myCarYear = 2004;
myCarKgs = 2000;
myCarColor = "blue";

function go() {
    alert("go!");
};

除了代码的组织方式之外,我不明白它的程序性如何。毕竟,语句是按顺序执行的。而且我不知道做这一切有什么好处。

我一直在想,为了理解这一点,我真正需要的是看两个程序做同样的事情,一个用正常的变量和函数编写程序,第二个用OO编程,以便看到差异和这些对象如何以有利的方式相互作用。

我发现我发现的所有教科书和网站都没有解释类似的事情是如何表现出不同的,或者为什么一个比另一个更好,如果有任何关于如何将它们组合在一起的例子很少。大多数书籍和教程只是告诉你你可以做什么,但不是为什么你想要这样做或选择一种方式而不是另一种方式。 (与这个问题无关,但我想知道的另一件事是,我知道我可以为变量分配一个函数,但我为什么要这样做呢?)

为了清楚我正在寻找什么,我的问题是,有人可以向我展示一个既可以编程的程序(两者都做同样的事情,并且对初学者来说足够简单但复杂到足以表明为什么OOP可能是需要或有利的)突出差异并解释为什么它更好?

3 个答案:

答案 0 :(得分:2)

说实话,我总是发现适当范围的变量的想法是javascript的OOP方法的一个很好的论据。

以你的例子为例:

var myCar = {
make: "Chevy",
year: 2004,

};

var make = "Ford";
console.log(make);
console.log(myCar.make);

收益“福特”,然后是“雪佛兰”。范围界定的原因可能是JS中的一个问题是可以引入的库的数量。是的,小程序往往更容易使用程序编写。但是当你进入其他几十个库时,你不知道它们用于声明变量的方法 - 这会导致模糊的错误。

是的,您可以在函数定义中声明变量,然后将它们限定为该函数(下面的示例),但是它们不能轻易地重用!

function go(){
var make = "chevy";
console.log(make);
};
go();
console.log(make) ///throws undefined 'error'

OOP提供了一种范围安全且易于重用的方法(这对于外部库非常有用)。

答案 1 :(得分:1)

他们说OOP是关于继承,多态和封装。

我们将封装放在一边,因为它与OOP无关,而是与模块无关。 (最后,modules是该语言的一部分!)

Inheritance是一个强大的概念,可以重用逻辑和数据。扩展您的汽车示例,我们可以执行以下操作。

var AbstractCar = {
    go: function () {
        alert('go ' + this.make+ '!');
    }
};
var MyCar = Object.create(AbstractCar, {
    make: { value: 'Chevy', writable: true }
});

var YourCar = Object.create(AbstractCar, {
    make: { value: 'Mustang', writable: true }
});

MyCar.go(); // go Chevy!
YourCar.go() // go Mustang!

另一方面,多态性允许您将不同类型的对象视为一个对象,只要它们符合接口即可。或者,换句话说,只要他们能够做到,我们希望他们这样做。

例如,我们需要一个out对象的字符串表示。任何具有toString方法的东西都可以与字符串连接。

var myCar = {
    make: "Chevy",
    year: 2004,
    toString: function () {
        return this.make + ' ' + this.year;
    }
};

var statement = 'I want to sell ' + myCar;

console.log(statement); // I want to sell Chevy 2004

这就是它。

OOP并不是一种应该掌握其价值的优秀技术。虽然它可以很方便。 :)

答案 2 :(得分:1)

实际上,如果您有一个小脚本或应用程序,您将看不到差异。 但是一旦你转向更大的应用程序和更大的代码库,你就会发现OOP比PP更好。

以下是OOP方法相对于PP的一些高级优势:

1)模块化和可维护性

代码变为模块化,相关数据和方法被打包到对象中。

这使得控制代码变得更加容易。 在几行代码中看到这一点很复杂,但随着代码的增长,程序代码最常变成混乱。

使用OOP,您的代码自然会被分割成更小的部分(对象),甚至在代码库增长时,仍然可以很容易地保持代码的顺序。 模块化带来了更好的可维护性 - 更容易修改和维护代码。

2)灵活性

用一些不同的功能替换部分代码要容易得多。

例如,您可以拥有将日志写入文件的Logger对象。但是,您决定将日志写入数据库。

使用PP方法,您需要遍历整个代码库,搜索log_to_file(message, file_name)之类的内容,并替换为log_to_db(message, db, table_name)之类的内容。

使用OOP,您只需创建新的DbLogger和"将其插入"进入系统而不是以前的文件记录器,因此记录数据的代码看起来仍然相同,如logger->log(message)。更好的是,您可以决定记录器运行时的类型,例如,从配置文件中读取设置并创建文件记录器或db记录器。

3)可测试性

使用OOP,我们可以更轻松地获取代码(对象)并单独测试它。如果它依赖于其他对象,可以用假实现(测试模拟)替换它们,这样你就可以单独测试这段代码。

为了证明这一点,让我们想象一下,你现在有了三个(也就是go方法应该对变量做一些事情,而不是一辆车,否则它不会很有道理):

var myCarMake = "Chevy";
var myCarYear = 2004;
var myCarKgs = 2000;
var myCarColor = "blue";

var yourCarMake = "Ford";
var yourCarYear = 2001;
var yourCarKgs = 1990;
var yourCarColor = "white";

var hisCarMake = "Ferrari";
var hisCarYear = 2011;
var hisCarKgs = 2990;
var hisCarColor = "red";

function go(make, year, kgs, color) {
    alert(make + " " + kgs + " " + year + " " color);
};

go(myCarMake, myCarYear, myCarKgs, myCarColor);
go(yourCarMake, yourCarYear, yourCarKgs, myCarColor);
go(hisCarMake, hisCarKgs, hisCarKgs, hisCarColor);

请注意此代码的一些属性:

  • busness-logic代码(汽车属性的定义和go方法)与客户端代码(我们称之为go的部分)混合在一起,我们无法将它们分开,因为客户端代码指我们创建的全局变量(如myCarMake
  • 许多重复(如CarMake写入6次)并且看起来很乱
  • 容易出错(最后两次通话都有错误)
  • 难以维护 - 如果我们为汽车添加新参数,我们将不得不重新审视所有代码库

现在带有对象的版本(为了简化代码,我把它作为一个简单的对象和单独的构造函数,请参阅this了解其他定义对象的方法):

var CarPrototype = { // empty object-prototype
    make: "",
    year: 0,
    kilograms: 0,
    color: "",
    go: function() {
        alert(this.make + " " + this.kgs + " " + this.year + " " this.color);
    }
};

// function that constructs the new object
function createCar(make, kgs, year, color) {
    var car = Object.create(CarPrototype);
    car.make = make;
    car.kgs = kgs;
    car.year = year;
    car.color = color;
    return car;
}

var myCar = createCar("Chevy", 2004, 2000, "blue");
var yourCar = createCar("Ford", 2001, 1990, "white");
var hisCar = createCar("Ferrari", 2011, 2990, "red");

myCar.go();
yourCar.go();
hisCar.go();

此代码的一些属性:

  • 业务逻辑明确定义并与客户端代码分离,客户端代码不了解car对象的内部结构
  • 重复次数减少,一般情况下代码看起来更清晰
  • 一旦定义了对象,制作错误真的很复杂(你只做myCar->go(),没有参数传递,没有机会混合它们或传递错误的顺序
  • 更容易修改(如果我们为汽车添加新属性,则客户代码中的myCar.go()来电不需要更改)

当然,我没有提到使用OOP而不是PP的所有理由,但我从实践中知道这一点 - 尝试花一些时间学习OOP原则并开始使用它并且你会看到巨大的代码结构的改进。你会在一开始就犯错误并做错事,但结果总是比程序代码更好。

这里的一般方法比特定的语言结构更重要,你可以在C(不是OOP语言)和javascript(具有特定的OOP支持)以及其他语言中使用相同的原则。

我不知道将PP和OOP并排比较的资源,但我认为您并不真正需要它。只要看一下OOP应用程序的例子,想象一下如果用程序风格编写它们会是什么样子。

我最喜欢的关于OOP的书是Design Patterns,它展示了对象之间的交互是多么优雅和强大。 或许,您还需要找到解释基本OOP概念的something(已提及encapsulationpolymorphisminheritance)和原则(最值得注意的是SOLID )。