JavaScript:是否值得将变量设为私有并定义getter/setter?

def*_*NJA 9 javascript oop coding-style class web-standards

我想首先说我明白JavaScript是一种无类语言.我的背景是Java,C++和Objective-C,它们都是支持Classes的经典OOP语言.

我正在扩展到Web开发,并一直在尝试使用JavaScript并学习它的模式.现在我正在使用在JavaScript中模拟类的构造函数模式.

所以这是我的"练习"课程:

function Car( model, year, miles ) {
    this.model = model;
    this.year = year;
    this.miles = miles;

    var privateVarTest = 10;

    this.getPrivateVarTest = function() {
        return privateVarTest;
    }

    this.setPrivateVarTest = function( value ) {
        privateVarTest = value;
    }
}

Car.prototype.toString = function() {
    return this.model + " is a " + this.year + " model and has " + 
           this.miles + " miles.";
}

var myCar = new Car( "Ford Focus", "2006", "65,000" );
document.getElementById('notepad').innerHTML += '</br> Testing </br>';
document.getElementById('notepad').innerHTML += myCar.toString() + '</br>';
document.getElementById('notepad').innerHTML += myCar.model + '</br>';
document.getElementById('notepad').innerHTML += myCar.getPrivateVarTest() + '</br>';
myCar.setPrivateVarTest( 20 );
document.getElementById('notepad').innerHTML += myCar.getPrivateVarTest() + '</br>';
Run Code Online (Sandbox Code Playgroud)

现在我喜欢使用prototype定义函数的方式,因为它没有为每个Car创建的Object 实例化一个新版本的函数.但是,在经典的OOP语言中,我们private创建变量并创建public函数/方法来根据需要设置和获取这些变量.

JavaScript作为无类没有privatepublic用于该用途的关键词,所以我想我会用"伪造"一户一法实验private变量,当发现使用的var,而不是this必不可少使其不可访问的出边constructor,但我能够定义允许我的getter和setter.

现在最后我的问题,抱歉长时间的结束.对于经验丰富的JavaScript程序员的最佳实践,您是否会使所有变量private都遵循其他OOP语言的标准,并设置getter和setter(不能为每个Object创建强制创建的原型),或者尽可能地避免它们,因为this关键字基本上可以让你获得和设置你想要的所有东西,并且只private用于硬编码类所需的一些内部数据?

感谢您花时间阅读本文并提供讨论,我真的只是想了解经验丰富的Web开发人员所使用的最佳实践标准.

Eri*_*pen 21

一般OOP

无论你在编写什么语言代码,我都在营地里,吸气者和制定者在很大程度上完全是毫无意义和愚蠢的.

在大多数情况下,暴露的属性应该是罕见的,因为对象的任何属性通常应该在对象的域内,因此只有对象实际上应该更改自己的内部作为其他操作的副作用,而不是因为某些其他对象直接告诉它改变一些事情.有一些例外我肯定(总有)但我记不清上次我需要制作一个.

此外,当公开属性时,使用方法公开的唯一原因是因为您不能仅仅因语言限制(Java)而公开属性,或者因为在更改该属性时必须进行某些验证或通知.只是简单介绍Java-bean风格的方法,除了实际改变或返回属性之外什么都不做,这对保留封装没有任何帮助.如果可以的话,您也可以将该物业公之于众.

但是,想要从各地获取/设置所有内容的真正问题在于,您基本上只是编写了链式过程代码并将其称为OOP.你仍然有很长的一系列事情,只能用一个接一个的事情来推理.使用OOP,我们的想法是避免长缠绕的意大利面链,这样您就可以从更大的结构角度更多地查看您的体系结构,这些结构在关键点拥有特定的域.如果没有这个,你或许可以通过至少在命名空间下对函数进行分类来减少意大利面的影响,这样就可以更容易地知道在哪里寻找东西但是你并没有真正利用OOP可以为你的架构提供的关键胜利.

私有或在JS的情况下本地构造函数/工厂关闭变量的真正价值是信号意图.如果它暴露出来,外在的东西真的应该改变它.如果不是,那么你已经明确表示var只是对象的业务.

JS OOP

我的建议是忘记JS中的类模拟.这完全没必要.一旦您了解原型,原型就会变得优雅和简单.将构造函数的prototype属性视为一种备份对象.如果在一个它没有的实例上调用方法,则下一步是检查实例的构造函数的原型对象属性.如果该对象没有它,那么它的构造函数的原型对象将被检查,依此类推,直到你最终到达核心Object构造函数的原型.

这是因为在查找过程中你可以动态地向构造函数添加新方法,并且所有实例在构建之后都"继承"它,但它不是真正的继承,而是一个回退过程.

JS中的继承很简单.这并不意味着你应该做大量的事情.级联继承的长链被认为是任何语言中的反模式有充分的理由,并且由于回调过程的工作方式,如果你通过类似18级原型攻击调用对象,它也可以真正地杀死perf. JS中的每一件小事.我想说复合对象更喜欢继承,当继承看起来像一个更明智的选项时,每当你想通过链中超过2-3个原型链接继承时,请检查自己.

哦,还有一个JS需要在构造函数中将本地实例变量视为私有属性:这只是JS在函数范围上下文中的闭包规则.在原型中或在构造函数外部声明的方法无法访问那些内部变量.使用new关键字调用的构造函数更改了"this"访问的规则,并且它们留下了一个实例,但是以其他方式执行JS函数.

在JS OOP中,疯狂但又疯狂的值得理解的其他风格是apply,call和now bind方法.我倾向于将这些更多地视为工厂中您想要的东西,但它们非常强大.

一旦你掌握了JS OOP,从功能角度开始理解JS,你会发现它有一个非常强大的1-2拳击组合.我们可以使用JS中的最少代码轻松完成任何事情.设计权衡是性能(现代JIT编译器处理得非常好)并且它为您提供了充足的绳索.我更喜欢绳子.自我私刑并不好玩,但这是学习/开发更好的直觉过程的一部分,结果发生得更快,并导致长期可维护的代码更多.虽然Java基本上强制执行OOP,但由于对开发人员做愚蠢的事情而言过于保护主义,导致社区广泛采用与OOP的全部要点完全相反的做法.

简短版本:

  • 如果你这样做,不管语言如何,都要停止/设置很多.它首先大大降低了实施OOP的胜利因素.
  • 原型非常简单,优雅,功能强大.修补他们.学习它们.但要注意.相比之下,课程可能会开始变得过时,笨拙和过度(尽管在非解释性语言中是公平的,完全必要的).
  • 为了让JS能够很好地为你工作,你可以自我学习你碰巧遇到的任何方面的废话.原始优雅语言能力的回报超过了花费的时间.与你所熟悉的语言相比,JS更接近于Scheme,所以它很奇怪,但它没有任意奇怪或没有设计原则,而且JS在网络用户界面中的主导成功并非偶然,无论人们告诉每个人我们是什么"被卡住了"用它"会让你相信.
  • 完全披露:我不喜欢Java.

更新:

es6 class关键字几乎没有改变JS中的OOP.这是100%的语法糖.IMO,"class"这个词的使用并没有给新人带来任何好处,但是JS中的所有三种对象构造函数/创建和对象实例化都存在优点/缺点,它们都值得了解/理解.这三种方法是构造函数,Object.create,现在是class关键字.