JS++
| 패러다임 | 다중 패러다임: 명령형, 구조적, 객체 지향, 함수형, 제네릭 |
|---|---|
| 계열 | ECMA스크립트 |
| 설계자 | 로저 푼(Roger Poon), 안톤 라페토프(Anton Rapetov) |
| 개발자 | Onux |
| 발표일 | 2011년 10월 8일 |
| 최근 버전 | 0.10.0 |
| 최근 버전 출시일 | 2021년 12월 10일 |
| 자료형 체계 | 점진적, 정적, 동적 |
| 변수 영역 | 렉시컬 |
| 라이선스 | BSD |
| 파일 확장자 | .jspp, .js++, .jpp |
| 웹사이트 | www |
| 영향을 받은 언어 | |
| C, C++, C#, 자바, 자바스크립트 | |
JS++는 자바스크립트를 건전한 타입 시스템으로 확장한 웹 개발용 프로그래밍 언어이다. 이 언어는 명령형, 객체 지향, 함수형, 그리고 제네릭 프로그래밍 기능을 포함한다. BSD 라이선스로 배포되는 자유-오픈 소스 소프트웨어이다.
역사
[편집]JS++은 2011년 10월 8일에 처음 등장했다.[1][2][3] 현대적인 구현체는 2016년 DeveloperWeek에서 발표되었으며[4] 2016년 5월 31일에 출시되었다.[5][6][7][8] 이 언어는 로저 푼과 안톤 라페토프가 설계했다.
기능
[편집]건전한 점진적 타입 시스템
[편집]JS++은 자바스크립트의 상위 집합이므로 변수에 대한 자료형 선언은 선택 사항이다. 그러나 타입을 선언하면 컴파일 타임과 런타임 모두에서 타입이 강제된다.
JS++의 타입 어노테이션은 전통적인 C/C++ 문법을 사용한다.
int x = 1;
var y = 2;
bool z = true;
특히 이는 더 장황한 스타일을 사용하는 타입스크립트 및 액션스크립트와 차별화된다.
var x: number = 1;
var y: any = 2;
var z: boolean = true;
JS++의 타입 시스템은 호스트 객체, 동적 키-값 쌍, 코멧, J스크립트 조건부 컴파일, 동적 반환 타입, 액티브X, ECMAScript for XML, 웹 브라우저 가비지 컬렉터 및 순환 참조 카운팅 버그, 조건부 논리, 그 외의 다양한 엣지 케이스를 포함하는 ECMA스크립트 및 DOM API의 예외적인 상황에 대해 건전하다.[9][10] 이는 타입스크립트와 같이 타입이 선택 사항이며 타입 소거를 통해 런타임에 제거되는 다른 자바스크립트 상위 집합과는 다르다.[11][12]
자바스크립트 라이브러리 가져오기
[편집]JS++은 다음의 JS++ 홈페이지 예제와 같이 한 줄의 external 문을 사용하여 자바스크립트 라이브러리를 사용할 수 있다.
import System;
// 한 줄의 코드로 자바스크립트 라이브러리 가져오기
external jQuery, $;
class Example {
public Example() {
// 학습 곡선이 거의 없음
// 일반 자바스크립트를 계속 작성할 수 있음
var a = 0, random = Math.random();
// 정수 타입 및 기타 원시 타입
// ... 빠른(최적화된) 코드와 명확한 코드를 가능하게 함
byte[] rgbColors = [ 0xFF, 0xFA, 0xFF ];
}
public void showMessage(int id, string text) {
// 일반 자바스크립트와 100% 호환
jQuery("#msgbox").show();
$("#msgbox").text(id.toString() + text);
}
}
객체 지향 프로그래밍
[편집]자바스크립트 (ECMA스크립트 6)의 클래스가 내부적으로는 프로토타입을 위한 신택틱 슈거인 반면,[13] JS++의 클래스는 메모리 레이아웃, 성능, 의미론적 측면에서 C++, 자바, C#과 같은 고전적인 프로그래밍 언어에서 볼 수 있는 클래스와 유사하다. "클래스"는 정적 개념이며, 자바스크립트, 스몰토크, 리스프, 타입스크립트처럼 프로토타입에 의존하여 런타임(프로그램 실행 중)에 변경할 수 없다.[14] 예를 들어, private 메소드는 컴파일 타임과 런타임 모두에서 private 상태를 유지하며, 자바스크립트에서 JS++ 객체에 대한 참조를 얻더라도 외부 자바스크립트 객체는 JS++의 private 필드나 메소드에 접근할 수 없다.
예제: 객체 지향 정렬
[편집]다음 소스 코드는 타입 안전하고 가독성 높은 비교를 위해 IComparable<T> 인터페이스와 Comparison 열거형을 사용하는 JS++의 객체 지향 정렬을 보여준다.[15] 사용자 정의 정렬 로직은 아래의 오버라이드된 compare 메소드에서 한 줄의 코드로 구현된다.
import System;
class Employee : IComparable<Employee> {
private string firstName;
private string lastName;
public Employee(string firstName, string lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public override Comparison compare(Employee that) {
// 성(surname)으로 정렬
return this.lastName.compare(that.lastName);
}
public override string toString() {
return this.firstName + " " + this.lastName;
}
}
Employee zig = new Employee("Zig", "Ziglar");
Employee john = new Employee("John", "Smith");
Employee abe = new Employee("Abe", "Lincoln");
Employee[] employees = [ zig, john, abe ];
employees.sort();
Console.log(employees.join(", "));
Abe Lincoln, John Smith, Zig Ziglar
위의 코드에서 제공된 사용자 정의 정렬 로직은 다음과 같다.
return this.lastName.compare(that.lastName);
마찬가지로, 정렬 호출은 다음과 같다.
employees.sort();
정렬된 결과 출력은 다음과 같다.
Console.log(employees.join(", "));
예제: 기본 캡슐화
[편집]JS++은 기본적으로 캡슐화를 제공한다. 다음 예제에서 x와 y 필드는 접근 제어자가 지정되지 않아도 기본적으로 private이다. getX()와 getY() 메소드는 기본적으로 public이다. 이를 통해 아래 Point 클래스에서 볼 수 있듯이 더 간결한 클래스 정의 문법이 가능하다.[16]
class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
int getX() {
return this.x;
}
int getY() {
return this.y;
}
}
경계 외부(Out-of-bounds) 분석
[편집]경계 외부(out-of-bounds) 접근은 일반적으로 배열 및 기타 컨테이너에서 발생한다. 예를 들어, 3개 요소로 구성된 배열의 100번째 요소에 접근하면 경계 외부 접근이 발생한다.
int[] arr = [ 1, 2, 3 ];
Console.log(arr[100]); // 경계 외부 접근, 'arr'은 인덱스 100에 요소가 없음
자바나 C#에서는 이로 인해 예외가 발생하고 프로그램이 종료될 수 있다. C에서는 버퍼 오버플로나 세그멘테이션 오류가 발생할 수 있다. C++은 기본 초기화, 예외, 세그멘테이션 오류, 버퍼 오버플로 등 다양한 의미론을 가진다.[17][18]
JS++은 컴파일 타임에 경계 외부 오류를 효율적으로 분석하고 방지할 수 있다.[19][20][21]
자바스크립트에는 null과 undefined 값이 존재하는데, null은 값이 존재하지만 빈 값임을 의미하고, undefined는 값이 전혀 없음을 의미한다. JS++은 이 직관을 더 확장하여 빈 값과 경계 외부 접근을 구분한다.[21]
int?로 표현되는 널러블 int 타입이 있는 다음 코드를 고려하자.
int[] a = [ 1, 2 ];
int? value1 = a[2];
if (value1 == null) {
Console.log("분명히 경계 외부임");
}
int?[] b = [ 1, null ];
int? value2 = b[2];
if (value2 == null) {
Console.log("경계 외부일 수도 있고, 단순히 null 요소에 접근했을 수도 있음");
}
널러블 타입이 경계 외부 접근을 나타낼 수는 있지만, 위와 같이 배열이 널러블 값을 포함할 수 있는 경우에는 작동하지 않는다. 대신 JS++은 널 값 외에 추가적인 개념인 '정의되지 않은(undefined) 값'을 도입한다. JS++은 자바스크립트의 개념을 확장하여 null은 값이 있지만 빈 값임을, undefined는 값이 아예 존재하지 않음을 의미하도록 한다. JS++은 "값이 아예 존재하지 않음"이라는 개념을 경계 외부 접근이 발생했음을 의미하는 것으로 사용하며, 이 개념은 JS++에서 "존재 타입(existent types)"으로 알려져 있다.[21]
따라서 이전 예제를 수정할 수 있다. 존재 타입 int+는 "int 또는 경계 외부"를 의미하고, int?+는 "int, null, 또는 경계 외부"를 의미한다.
int[] a = [ 1, 2 ];
int? value1 = a[2];
if (value1 == undefined) {
Console.log("분명히 경계 외부임");
}
int?[] b = [ 1, null ];
int?+ value2 = b[2];
if (value2 == undefined) {
Console.log("분명히 경계 외부임");
}
직관적으로 이는 존재 타입을 배열 요소의 기본 타입으로 사용할 수 없음을 의미한다. JS++은 이를 컴파일 타임에 강제한다.
int+[] arr = []; // 오류
[ 오류 ] JSPPE5204: 존재 타입 `int+'는 배열의 요소 타입으로 사용할 수 없음
경로 폭발과 지수적인 컴파일 시간을 초래할 수 있는 모든 조건부 분기나 가상 메소드 호출 경로를 따르는 대신, 존재 타입은 기본적으로 int, bool 및 기타 원시 타입과 동일한 컴파일 타임 분석 비용을 가진다. 결과적으로 컴파일 시간은 존재 타입 도입의 영향을 받지 않는 것으로 나타났다(±1-2ms).[21] 존재 타입은 JS++의 모든 배열 및 컨테이너 타입(예: 해시 맵, Stack<T>, Queue<T>)에 사용되므로 JS++ 컨테이너는 경계 외부 오류가 발생하지 않음이 보장된다.
JS++에서 undefined는 변경할 수 없는 값이다. 자바스크립트 (ECMA스크립트 3)에서 undefined는 전역 객체의 변경 가능한 속성이어서 "undefined"가 "정의"될 수 있는 상황이 발생할 수 있다.[22] 따라서 순수 자바스크립트에서는 존재 타입을 구현할 수 없는데, 이는 배열에 undefined 값이 포함될 수 있고, undefined가 정의될 수 있으며, JS++에서 방지되는 다른 예외 사례들 때문이기도 하다.[21][23]
또한 자바나 에펠과 같은 초기 객체 지향 언어들과 비교하여,[24][25] JS++은 객체를 null로 기본 초기화하지 않는다.[21] 대신 컴파일러가 프로그래머에 의한 초기화를 강제한다.
class Car {}
Car car;
[ 오류 ] JSPPE6000: 변수 `car'가 3행 4열에서 초기화되지 않음
따라서 존재 타입이 언어에 깊이 내장되어 있으므로 JS++은 경계 외부 오류가 절대 발생하지 않음을 보장할 수 있다.[26][10]
데이터베이스
[편집]존재 타입의 개념은 컨테이너 외부로 확장될 수 있다. 예를 들어 MySQL에서 컬럼은 널러블일 수 있다.[27][28] 특정 조건(예: WHERE 절)에 대해 행이 존재하지 않으면 undefined 값이 반환될 수 있다. 그러나 행은 존재하지만 해당 컬럼의 값이 비어 있는 경우 대신 null 값이 반환될 수 있다. 이는 데이터 접근 계층으로의 코드와 인터페이스를 단순화할 수 있다.
정수 타입
[편집]JS++은 8비트, 16비트, 32비트, 64비트 정수 타입뿐만 아니라 부동 소수점 타입을 제공한다.
byte b1 = 0xFF; // 부호 없는 8비트
signed byte b2 = -1; // 부호 있는 8비트
short s1 = 1; // 부호 있는 16비트
unsigned short s2 = 1; // 부호 없는 16비트
int x1 = 0; // 부호 있는 32비트
unsigned int x2 = 0; // 부호 없는 32비트
long z1 = 1; // 부호 있는 64비트
unsigned long z2 = 1; // 부호 없는 64비트
float f = 0.5; // 단정밀도 부동 소수점
double d = 0.5; // 배정밀도 부동 소수점
프로젝트 홈페이지의 예제:
// 변수의 타입을 선언할 필요가 없으며 일반 자바스크립트를
// 그대로 계속 작성할 수 있음 (다시 한번 말하지만, 학습 곡선이 없음):
var offset = 0;
// 하지만 타입을 선언하면, 이 다음 변수는 런타임에서도 항상 'unsigned int'로 유지됨.
// 다시는 NaN("Not a Number") 런타임 오류를 보지 않아도 됨.
// 이 변수는 'unsigned'이므로 음수가 되지 않음이 보장됨.
unsigned int pageHeight = $(document).height();
블록 범위(Block scoping)
[편집]자바스크립트 var 문을 포함하여 JS++의 모든 변수는 블록 범위이다.[29][30][31] 따라서 자바스크립트 (ECMA스크립트 6)에서 var와 let이 동시에 존재하는 것처럼 서로 다른 범위 규칙을 가진 두 가지 변수 선언 키워드가 필요하지 않다.
개발 도구
[편집]컴파일러
[편집]JS++ 컴파일러는 윈도우, MacOS, 리눅스에서 사용할 수 있다. 이 컴파일러는 중간 표현으로서 자바스크립트 소스 코드를 내보내는 소스 대 소스 컴파일러이다.
컴파일러는 C/C++로 개발되었으며, 개발자들은 3.5년의 엔지니어링과 40만 줄의 코드 끝에 "핵심 컴파일러에 열린 버그 보고서가 10개 미만"이라고 주장한다.[31][32]
편집기 통합
[편집]JS++은 비주얼 스튜디오 코드, 아톰, 서브라임 텍스트를 포함한 다양한 코드 편집기와 통합된다.[33][34][35]
빌드 도구
[편집]릴리스 기록
[편집]| 버전 번호 | 릴리스 날짜 | 변경 사항 |
|---|---|---|
| 0.01 | 2011년 10월 8일 | 알파 버전, 최초 릴리스 |
| 0.011 | 2011년 10월 10일 | 알파 버전 |
| 0.012 | 2011년 10월 25일 | 알파 버전 |
| 0.013 | 2012년 1월 29일 | 알파 버전 |
| 0.014.1 | 2012년 8월 15일 | 알파 버전 |
| 0.4.1 | 2016년 5월 31일 | 베타 버전, 배열 및 콜백 타입, 문자 리터럴, 정수형 접미사, ECMAScript ASI 제거 |
| 0.4.2 | 2016년 10월 18일 | 모듈, 함수 오버로딩, 데드 코드 제거, 편집기 통합 |
| 0.4.2.1 | 2016년 10월 24일 | 버그 수정 |
| 0.4.2.2 | 2016년 11월 17일 | 소스 맵 디버깅 |
| 0.4.2.4 | 2016년 12월 25일 | Mac OS X 지원, C 스타일 캐스트, 콜백 및 배열 변환 |
| 0.5.0 | 2017년 3월 13일 | 클래스 |
| 0.5.1 | 2017년 3월 26일 | 'foreach' 루프 |
| 0.5.2 | 2017년 7월 27일 | BSD 허가서, 인터페이스, 추상 클래스, 가상 메소드, 자동 박싱 |
| 0.7.0 | 2017년 10월 27일 | Array<T> 및 표준 라이브러리를 통한 모든 ECMA스크립트 3 기능 |
| 0.8.0 | 2018년 3월 15일 | 제네릭 프로그래밍, Dictionary<T>, 멀티라인 문자열, .js++ 파일 확장자 |
| 0.8.1 | 2018년 3월 27일 | auto, catch-all 절, 시간 처리를 위한 표준 라이브러리 모듈, 버그 수정 |
| 0.8.4 | 2018년 5월 23일 | 새로운 문자열 함수, 고급 제네릭, 버그 수정, 표준 라이브러리 확장 |
| 0.8.5 | 2018년 6월 2일 | 버그 수정 |
| 0.8.10 | 2018년 11월 24일 | 더 빠른 컴파일 시간, 스택, 큐, 유니코드, 베이스64, 제네릭 기본 제약 규칙 |
| 0.9.0 | 2019년 1월 11일 | 효율적인 컴파일 타임 경계 외부 오류 분석 |
| 0.9.1 | 2019년 7월 1일 | 버그 수정 |
| 0.9.2 | 2019년 10월 18일 | 최종(불변) 변수 및 macOS 카탈리나를 위한 64비트 컴퓨팅 기본 설정 |
같이 보기
[편집]각주
[편집]- ↑ “JavaScript++: New, Powerful Language for Better Web Development”. 2011년 10월 17일. 2011년 10월 17일에 원본 문서에서 보존된 문서.
- ↑ “C++ et Javascript = Javascript++”. 《La ferme du web》. 2011년 10월 12일. 2011년 10월 12일에 원본 문서에서 보존된 문서.
- ↑ “Index of /downloads”. 2011년 10월 18일. 2011년 10월 18일에 원본 문서에서 보존된 문서.
- ↑ “JavaScript Conference - DeveloperWeek 2016 - February 12–18”. 2016년 2월 13일. 2016년 2월 13일에 원본 문서에서 보존된 문서.
- ↑ Poon, Roger (2016년 5월 31일). “JS++ Goes Into Public Beta”. 《Onux.com》.
- ↑ Handy, Alex (2016년 6월 1일). “Onux seeks to fix JavaScript's lack of type safety”. 《SD Times》.
- ↑ Krill, Paul (2016년 6월 6일). “New compiler tackles JavaScript's weak typing”. 《InfoWorld》.
- ↑ Cimpanu, Catalin (2016년 6월 9일). “jQuery 3.0 Released and Other JavaScript News”. 《Softpedia》.
- ↑ “The JS++ Type System, Appendix B: Problems (Why was this hard to solve?)”. 2020년 2월 10일에 확인함.
- 1 2 US patent 10296313, Roger Poon, "Safely consuming dynamically-typed code from a statically-typed programming language", published 2019-05-21
- ↑ Bridgwater, Adrian (2016년 6월 13일). “Onux JS++, an answer to JavaScript 'brittle' type safety?”. 《Computer Weekly》. 2016년 7월 22일에 원본 문서에서 보존된 문서.
- ↑ “The JS++ Type System”. 《Onux.com》.
- ↑ “Classes”. MDN 웹 문서. 2025년 6월 20일에 확인함.
- ↑ Meyer, Bertrand (1988). 《객체 지향 소프트웨어 구성》. 94,100쪽.
- ↑ Poon, Roger (2019년 5월 28일). “Tips & Tricks: Object-oriented Sorting in JS++ with IComparable<T>”. 2025년 6월 20일에 확인함.
- ↑ Poon, Roger (2018년 6월 10일). “Tips & Tricks: Only Fields are 'private' by Default”. 2025년 6월 20일에 확인함.
- ↑ “std::unordered_map<Key,T,Hash,KeyEqual,Allocator>::operator[] - cppreference.com”. 《en.cppreference.com》. 2025년 6월 20일에 확인함.
- ↑ “std::unordered_map<Key,T,Hash,KeyEqual,Allocator>::at - cppreference.com”. 《en.cppreference.com》. 2025년 6월 20일에 확인함.
- ↑ Díaz, Fabio (2019년 1월 23일). “JS++, the JavaScript superset, is getting rid of out-of-bounds errors”. 《Akuaroworld》. 2019년 2월 1일에 원본 문서에서 보존된 문서. 2019년 2월 1일에 확인함.
- ↑ Cardoza, Christina (2019년 1월 16일). “JS++ programming language looks to solve out-of-bounds errors”. 《SD Times》.
- 1 2 3 4 5 6 Poon, Roger (2019년 1월 11일). “JS++ 0.9.0: Efficient Compile Time Analysis of Out-of-Bounds Errors”. 《Onux.com》.
- ↑ “ECMAScript Language Specification”. Ecma 인터내셔널. 2000년 3월 24일: 86.
- ↑ “Compatibility with JavaScript - JS++ & JavaScript Documentation”. 2025년 6월 20일에 확인함.
- ↑ Meyer, Bertrand (1988). 《객체 지향 소프트웨어 구성》. 70–77쪽.
- ↑ “Void-safety: Background, definition, and tools”. 에펠. 2025년 6월 24일에 확인함.
- ↑ US patent 11023214, Roger Poon & Anton Rapetov, "Preventing runtime out-of-bounds errors and exceptions with nominal types", published 2021-06-01
- ↑ “MySQL :: MySQL 8.4 Reference Manual :: 13.6 Data Type Default Values”. MySQL. 2025년 6월 20일에 확인함.
- ↑ “MySQL :: MySQL 8.4 Reference Manual :: 5.3.4.6 Working with NULL Values”. MySQL. 2025년 6월 20일에 확인함.
- ↑ “Scoping - JS++ & JavaScript Documentation”. 2025년 6월 24일에 확인함.
- ↑ “Compatibility with JavaScript - JS++ & JavaScript Documentation”. 2025년 6월 24일에 확인함.
- 1 2 “JS++ 0.9.1: Bug Fixes”. July 2019.
- ↑ Poon, Roger (2019년 10월 9일). “Compiler Software Engineering Methods”. 2025년 6월 24일에 확인함.
- ↑ “JavaScript superset JS++ adds dead code elimination and more”. 《컴퓨터월드》. 2016년 10월 19일. 2019년 2월 1일에 원본 문서에서 보존된 문서. 2026년 6월 20일에 확인함.
- ↑ Cardoza, Christina (2016년 10월 19일). “JS++ 0.4.2 released with code editor integrations, modules and dead code elimination”. 《SD Times》.
- ↑ Clark, Geneva (2016년 10월 20일). “JS++ 0.4.2 Release - Upgraded With Modular Design, Dead Code Elimination, and Multiple Code Editors”. 《Zeomag》.
- ↑ Phoenix, Ingwie (2018년 12월 7일). “Proof of Concept: Using JS++ with WebPack”. 《깃허브》. Ingwie Phoenix.