Underscore prefix for property and method names in JavaScript
javascript中的下划线前缀是否只是一种约定,例如在python私有类方法中?
从2.7 python文档中:
"Private" instance variables that
cannot be accessed except from inside
an object don’t exist in Python.
However, there is a convention that is
followed by most Python code: a name
prefixed with an underscore (e.g.
_spam) should be treated as a non-public part of the API (whether it
is a function, a method or a data
member).
这也适用于javascript吗?
以这个javascript代码为例:
1 2 3 4 5 6 7 8 9
| function AltTabPopup() {
this._init();
}
AltTabPopup.prototype = {
_init : function() {
...
}
} |
此外,还使用带下划线前缀的变量。
1 2 3 4 5 6
| ...
this._currentApp = 0;
this._currentWindow = -1;
this._thumbnailTimeoutId = 0;
this._motionTimeoutId = 0;
... |
只有约定?或者下划线前缀后面还有更多内容?
我承认我的问题与这个问题非常相似,但它并没有让人更聪明地理解javascript中下划线前缀的重要性。
- 另请参见stackoverflow.com/questions/17359885/…
那只是个惯例。javascript语言对以下划线字符开头的标识符没有任何特殊意义。
也就是说,对于不支持开箱即用封装的语言来说,这是一个非常有用的约定。虽然没有办法防止有人滥用你的类的实现,但至少它确实澄清了你的意图,并且首先记录了错误的行为。
- 是的。即使语言不"支持"它,它也是一个非常方便的约定。
- 严重的问题。jsfidle.net/vmfsr正如您所看到的,创建值的名称只能通过在新值前面加前缀来访问,创建值,使用_,我想知道发生了什么!为什么不是this.name代替?
- @穆罕默德·乌默尔,我不确定我是否理解你的评论。console.log(someone._name ="Jean Dupont");与console.log(someone.name);一样工作,它同时分配和评估属性后面带下划线的前缀成员。如您所见,不保证通过下划线进行封装:)
- 哇,我完全错过了仅仅赋值就足以声明某个东西的部分。我的错。谢谢你指出我快疯了。D
- 默认情况下,Visual Studio会帮助您尊重这一点。当使用"this"变量时,javascript intellisense引擎会从对象内部向您显示"private"属性。但是,当从外部调用时,它隐藏所有带下划线的属性。
Javascript实际上支持封装,通过一种在闭包中隐藏成员的方法(crockford)。这就是说,有时候很麻烦,而且下划线约定是一个很好的约定,可以用来处理一些私人事务,但实际上不需要隐藏。
- 向上投票以澄清如何实现关闭,向下投票以表示下划线是良好的惯例。所以我不会以任何方式投票。)
- 在闭包中隐藏成员有时会妨碍可测试性。查看本文:adequatelygood.com/2010/7/writing-testable-javascript
- @杰森-只是好奇,为什么你认为强调一个糟糕的惯例?
- @Tamaspap-有几个原因,但我的选择是:1)一个拐杖,迫使JS成为其他语言的风格2)如果可以访问,它将被使用。下划线会在代码外乱丢和卷积。3)让新的JS程序员感到困惑。
- @很明显,所有语言都可以访问jason-well-private,为什么这是一个缺点?
- 即使有了一个闭包,在技术上仍然可以访问所谓的"private"变量。《公约》至少让开发人员知道这样做的风险是他们自己承担的(或类似的事情)。
- @从技术上讲,您如何从闭包外部访问私有变量(在闭包中声明的var)?我的理解是,除非您继承范围(即使在作为func/对象原型一部分的方法中,您不会继承范围),否则您不能。
- @很抱歉,像gist.github.com/sarink/7394867这样的黑客攻击总是可能的。当然,您可以在一个框架中防范它。但如果有人能看到源头,他们肯定能找到一条路。
- "……"有点私密,但实际上你不需要隐藏的东西。"…或者你想私密的,也可以继承的东西。闭包中的变量不是可继承的afaik。
- @trusktr,ah,保护时间:)
- @Fr&233;D&233;Richamidi是的,受保护。:d据我所知,在javascript中没有办法做到这一点(有吗?).
- 这个链接太棒了,谢谢。
- @如果你和很多人一起编程,你就会明白为什么这是一个很好的约定。传统上,它意味着某些东西是私有的,但在javascript中,它也意味着,要知道,这可能会发生变化,所以您可能应该编写自己的方法/函数,使其更稳定。您试图避免(并传达给其他开发人员)的是,它在未来可能会发生变化,并且您不会为了向后兼容性而维护它;这意味着如果它破坏了代码,就由他们来修复它们的东西。
- @在这个例子中,kabirsarin允许一个人设置一个键,这个键可以被另一个方法调用(在本例中,这个键是push)。这比私人/公共曝光更糟糕,而且不是总是可能的。如果在附加中使用了_array[_array.length]=v,或者在存储中使用了防止使用push的密钥验证(例如,if(i!=='push')),则在该示例中不会出现问题(gist.github.com/sarink/7394867)。私有方法仍然可以影响全局范围的变量,甚至在其他语言中也是如此。
jsdoc 3允许您使用@access private标记(以前是@private标记)注释您的函数,这对于向其他开发人员传播您的意图也很有用-http://usejsdoc.org/tags-access.html
"Only conventions? Or is there more behind the underscore prefix?"
除了隐私约定,我还想帮助人们认识到下划线前缀也用于依赖独立参数的参数,特别是在URI锚定映射中。依赖键始终指向地图。
示例(来自https://github.com/mmikowski/urianchor):
1 2 3 4 5 6 7
| $.uriAnchor.setAnchor({
page : 'profile',
_page : {
uname : 'wendy',
online : 'today'
}
}); |
浏览器搜索字段上的URI锚定更改为:
1
| \#!page=profile:uname,wendy|online,today |
这是一种用于根据哈希更改驱动应用程序状态的约定。
import/export现在正与ES6合作。如果我的大部分函数是导出的,我仍然倾向于用_给未导出的函数加前缀。
如果只导出一个类(如在角度项目中),则根本不需要它。
1 2 3 4 5 6 7 8 9 10 11 12 13
| export class MyOpenClass{
open(){
doStuff()
this._privateStuff()
return close();
}
_privateStuff() { /* _ only as a convention */}
}
function close(){ /*... this is really private... */ } |
- 我不认为导入/导出以任何方式提供对私有类方法的支持。我的意思是,它在类级别上支持类似的功能,但是它不提供隐藏包含的方法。(即所有包含的方法始终是公共的)
- 导出类,内部函数调用外部函数。这些职能是私人的。