Префікс підкреслення для імен властивостей та методів у JavaScript


241

Чи є префікс підкреслення в JavaScript лише умовою, як, наприклад, у методах приватного класу Python?

З документації 2.7 Python:

"Приватні" змінні екземпляра, до яких не можна отримати доступ, крім усередині об'єкта, не існує в Python. Однак існує умова, за яким дотримується більшість кодів Python: ім'я з префіксом підкреслення (наприклад, _spam) слід трактувати як непублічну частину API (будь то функція, метод чи член даних) .

Це стосується і JavaScript?

Візьмемо для прикладу цей код JavaScript:

function AltTabPopup() {
    this._init();
}

AltTabPopup.prototype = {
    _init : function() {
        ...
    }
}

Також використовуються підкреслені префіксні змінні.

    ...
    this._currentApp = 0;
    this._currentWindow = -1;
    this._thumbnailTimeoutId = 0;
    this._motionTimeoutId = 0;
    ...

Тільки конвенції? Або є більше за префіксом підкреслення?


Я визнаю, моє запитання досить схоже на це запитання , але воно не зробило жодної розумнішої важливості префікса підкреслення в JavaScript.


Відповіді:


33

Ласкаво просимо до 2019 року!

Здається, було прийнято пропозицію про розширення синтаксису класу, щоб дозволити #приватну префікс бути приватною. Chrome 74 постачається з цією підтримкою.

_ префіксні назви змінних за умовами вважаються приватними, але все ще є загальнодоступними.

Цей синтаксис намагається бути як лаконічним, так і інтуїтивним, хоча він досить відрізняється від інших мов програмування.

Чому серед усіх точок коду Unicode був обраний sigil #?

  • @ був початковим фаворитом, але його взяли декоратори. TC39 розглядав можливість заміни декораторів та приватних державних знаків, але комітет вирішив перейти до існуючого використання користувачів транспілерів.
  • _ може спричинити проблеми сумісності з існуючим кодом JavaScript, що дозволяє _ на початку ідентифікатора чи (загальнодоступного) імені властивості протягом тривалого часу.

Ця пропозиція досягла 3 етапу в липні 2017 року. З цього часу великі роздуми та тривалі дискусії щодо різних альтернатив. Врешті-решт, цей роздум та продовження залучення громад призвели до відновлення консенсусу щодо пропозиції у цьому сховищі. Виходячи з цього консенсусу, впровадження цієї пропозиції рухається вперед.

Дивіться https://caniuse.com/#feat=mdn-javascript_classes_private_class_fields


257

Це лише умовність. Мова Javascript не надає особливого значення ідентифікаторам, починаючи з символів підкреслення.

Однак це є досить корисною умовою для мови, яка не підтримує інкапсуляцію . Хоча немає жодного способу запобігти зловживанню реалізацією ваших класів, принаймні це уточнює ваш намір і в першу чергу документує таку поведінку як неправильну .


4
Так. Навіть якщо мова не "підтримує" це, це дійсно зручна умова.
Juho Vepsäläinen

Серйозна проблема. jsfiddle.net/VmFSR Як ви бачите там, ім'я, створене значенням, доступне лише за допомогою префіксації нового значення, створеного, за допомогою якого _я б хотів знати, що відбувається !? чому це не this.nameзамість цього?
Мухаммед Умер

1
@Muhammad Umer, я не впевнений, що я розумію твій коментар. console.log(someone._name = "Jean Dupont");працює також добре console.log(someone.name);, і він призначає і оцінює підкреслений член із властивістю. Як бачите , Theres не гарантується інкапсуляцією через підкреслення :)
Frédéric Hamidi

3
За замовчуванням Visual Studio намагається допомогти вам це поважати. Двигун JavaScript IntelliSense показує вам "приватні" властивості зсередини об'єкта при використанні змінної "цей". Але, коли дзвонить ззовні, він приховує всі підкреслені атрибути.
foxontherock

1
@Karuhanga він відповів на це ще в 2010 році - звичайно, все змінилося за 10 років
Кенні Мейєр

99

JavaScript насправді підтримує інкапсуляцію за допомогою методу, який передбачає приховування членів у закриттях (Crockford). Однак, це іноді громіздко, і умовно-підкреслювальний конвент - це дуже хороша умова, яка використовується для речей, які є приватними, але які насправді не потрібно приховувати.


19
Вгору голосуйте за уточнення способів домогтися закриття, а голосування - за підкреслення - це хороша умова. Тому я не буду голосувати жодним чином :)
Джейсон

3
Приховування членів у закриттях іноді може перешкоджати встановленню. Перевірте цю статтю: adequatelygood.com/2010/7/Writing-Testable-JavaScript
Zach Lysobey

4
@Jason - Просто цікаво, чому ви вважаєте підкреслення поганою умовою?
Тамас Пап

5
@TamasPap - Кілька причин, але тільки мій варіант: 1) Милиця змусити JS до стилю інших мов 2) Якщо вона доступна, вона буде використана. Підкреслення може засмічуватися і згортати зовнішній код. 3) Конфуз для нових програмістів JS.
Джейсон

9
Навіть із закриттям, технічно все ж можливо отримати доступ до так званої "приватної" змінної. Конвенція, принаймні, дозволяє розробникам знати про це на свій страх і ризик (або щось подібне).
Саринк

14

JSDoc 3 дозволяє коментувати свої функції за допомогою @access private(раніше @privateтегу), який також корисний для трансляції вашого наміру іншим розробникам - http://usejsdoc.org/tags-access.html


10

"Тільки умовні позначення? Або за префіксом підкреслення є більше?"

Крім конвенцій про конфіденційність, я також хотів допомогти зрозуміти, що префікс підкреслення також використовується для аргументів, які залежать від незалежних аргументів, зокрема в картах якоря URI. Залежні клавіші завжди вказують на карту.

Приклад (з https://github.com/mmikowski/urianchor ):

$.uriAnchor.setAnchor({
  page   : 'profile',
  _page  : {
    uname   : 'wendy',
    online  : 'today'
  }
});

Якорь URI в полі пошуку браузера змінюється на:

\#!page=profile:uname,wendy|online,today

Це умова, що використовується для керування станом програми на основі змін хешу.


8

import/exportзараз виконує роботу з ES6. Я все ще схильний до префікса не експортованих функцій_ якщо більшість моїх функцій експортується.

Якщо ви експортуєте лише клас (як у кутових проектах), він взагалі не потрібен.

export class MyOpenClass{

    open(){
         doStuff()
         this._privateStuff()
         return close();
    }

    _privateStuff() { /* _ only as a convention */} 

}

function close(){ /*... this is really private... */ }

Я не думаю, що імпорт / експорт жодним чином не підтримує методи приватного класу. Я маю на увазі, він підтримує подібний функціонал на рівні класу, але він не пропонує приховувати містяться методи. (тобто всі вміщені методи завжди є загальнодоступними)
bvdb

Ви експортуєте зовнішню функцію класу та внутрішньої функції. Ці функції є приватними.
Ніколя Зозол
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.