原型编程 - 在 JavaScript 中构建类的正确方法
prototype programming - Correct way to build classes in JavaScript?
我是JavaScript的新手,并试图理解我应该如何编写类(我的"常规"OO语言背景,如Java和C ++)。
我知道我有两个选择:
-
如果我希望我的类有私有方法和成员,我无法在原型中定义它们。但在这种情况下,它们将为每个创建的新对象(内存问题)构建。
-
如果我在类原型中定义方法,我将没有封装(这对我来说很奇怪,作为一个 java/c++ 开发人员:P)。
您使用这两种方法中的哪一种?为什么?
所以,我认为这个问题没有"正确答案"......它基本上是您喜欢并认为最适合您的特定用途的。 我的许多类都是"静态类",例如
var MyClassName = {
methodName: function() { },
//...
}
因为我永远不需要实例化它们。 当我需要实例化多个实例时,我使用 prototype 方法。
如果你需要私有变量,你可以定义一个函数/类来做私有变量,以及需要访问该函数/类中的那些私有变量的方法。 然后,将原型方法用于不需要访问私有变量的所有方法。 例如
var PageClass = function() {
var _birthdate;
this.getBirthdate = function() {
return typeof(_birthdate) == "undefined" ? null : _birthdate;
}
this.setBirthdate = function( date ) {
if( typeof(date) == 'object' && date.constructor == Date ) {
_birthdate = date;
}
else {
throw "Invalid Argument Exception: PageClass.setBirthdate expects parameter of type 'Date'";
}
}
}
PageClass.prototype.doSomething = function() {
alert("DOING SOMETHING");
}
同时执行这两项操作应该使您能够使实例化重量更轻一些,但仍能为您提供一些封装。 到目前为止,我从未为私人变量而烦恼。
如果你使用的是原型框架,你最好使用他们实现类和继承的方式。你可能指的是这篇文章
通常我不认为私有成员在javascript中使用。(编辑:不在实例化类中。我经常在我们的代码库中看到一些"模块",它们确实拥有私有状态,但可以被视为单例)
凯文的回答几乎总结了这一点。从技术上讲,解决语言缺乏封装问题是可能的,但是如果您的类要被大量实例化,则需要付出代价。此外,我认为如果您要使用继承,则需要一些工作才能获得受保护的可见性。
例如,我认为在查看 ext 来源时我没有看到任何私人内容。他们确实将"//private"放在应该是私有的方法上,这表明不应该直接调用它们。这确实意味着如果你要以这种方式编码,你需要更多的"纪律"来编写getter/setter。
为什么是的有...现在。
上面的答案在他们的时代是正确的。
以下是新的解决方案:
'use strict';
// Declare our class
class Metadata {
// Declare the constructor and pass it some values - a and b are "defaults"
constructor( ninfo, a = 1.0, b = 1.0 )
{
// Set our class variables
this.ninfo = ninfo;
this.a = a;
this.b = b;
// Define our "secret" or nonenumerable options
Object.defineProperty( this, 'addA', {
enumerable: false,
writable: false,
// Have it add our passed in value
value: n => this.a += n
} );
}
}
// Call our class and pass in some variables
let x = new Metadata( "we have a and b", 1.0 );
// Log our result if we call "addA"
console.log( x.addA( 3 ) ); // => 4
// Log our object
console.log( x ); // => Metadata { ninfo: 'we have a and b', a: 4, b: 2 }
// Log our object 'for real'
console.log( require( 'util' ).inspect( x, { showHidden: true, depth: null } ) );
// result
// Metadata {
// ninfo: 'we have a and b',
// a: 4,
// b: 2,
// [addA]: { [Function: value] [length]: 1, [name]: 'value' } }
- 有没有一种方法可以基于Angular 2中注册的路线构建动态导航/菜单
- 有没有一种正确的方法可以通过jQuery构建HTML
- 在没有服务器根访问权限的情况下构建聊天脚本的有效方法是什么
- 电话差距构建地理位置 NPObject 上的错误调用方法
- 使用JQuery构建选项卡,这是最高效和最有效的方法
- 如何在 jquery 成功方法中接收 JSON 并使用该 JSON 构建 HTML 内容
- 用于构建用于查询的 JSON 数据的有效方法
- 在构建器中更改 z 索引的最简单方法
- 寻找一种使用 jquery 构建滚动条的简单方法
- 在 jquery 中为内联 css 构建图像路径的最佳方法
- 在PHP和Ajax中构建安全测验的好方法
- 在创建Javascript“类”的实例时,有没有办法构建对象,以便可以访问所有方法
- 通过JavaScript中的dictionary对象检查单词的有效性-是否有更好的方法来引用/构建词典
- 在jQuery中构建html元素的最清晰方法
- 使用CoreOS和多个Docker容器构建应用程序的正确方法
- 在underscore.js中使用相同的json分别构建表标题和数据的最佳方法
- 构建此字符串的最快方法
- 有没有更好的方法来构建我的NPM脚本,使它们更可读
- 使用模块化方法构建JavaScript应用程序
- 将API方法构建为角度服务