모던 JavaScript 튜토리얼 파트 1 :: 3장 "코드 품질", 4장 "객체:기본" 정리
모던 JavaScript 튜토리얼 3장, 4장을 읽으면서 정리하는 글입니다.
3장 코드 품질
Chrome으로 디버깅하기
Chrome으로 디버깅하기
ko.javascript.info
브라우저는 JS를 실행시켜줍니다. 이런 브라우저에도 Javascript에 대한 것을 디버깅할 수 있는 기능이 내장되어 있습니다.

왼쪽 탭을 보시면 Thread, Watch, Breakpoints, Scope, Call Stack, 등의 익숙한 용어들이 보입니다.
다른 개발 툴과 같이 Step in/out/into, break point 등 기능이 다 있습니다.
단축키와 같은 것은 모던 Javascript 책에 잘 설명되어 있기 때문에 스킵하겠습니다. ㅎㅎ
사실 컴포넌트라는 개념은 리액트 전에도 있던 개념입니다 ㅎㅎ.
Web Component, shadow DOM으로 프레임워크 없이도 컴포넌트 기반으로 개발할 수 있습니다.
저는 디버거로 GitHub을 살펴보았습니다. GitHub가 리액트 같은 라이브러리를 안 쓰고 순수하게 JavaScript의 WebComponent를 사용해서 개발한 사이트로 유명합니다. 물론 쌩으로 쓰진 않고 Lit와 같은 라이브러리를 사용합니다.

Lit란?

아무튼 이런 특성을 가지고 있는 GitHub을 살펴봅시다.
hasLoadingFragments에 breakpoint를 걸어보았습니다.

계속 Continue(F8) 시켜보면 로딩하는 Fragment를 불러올 때마다 멈추는 것을 볼 수 있습니다.
아무튼 Source Map이 있으니깐 이것저것 둘러보기 편하네용. 너무 내용이 산으로 가는 것 같아서 Lit 사이트 둘러보는 것은 따로 내용을 정리해보도록 하겠습니다.
코딩 스타일
코딩 스타일
ko.javascript.info
간결하고 읽기 쉬운 코드에 관한 내용입니다.
사실 이런 스타일은 사람(혹은 팀)마다 조금씩 갈립니다.
제가 쓰는 린트랑 프로젝트를 하면서 느낀 경험을 얘기하고 넘어가겠습니다.
탭 사이즈는 2칸이 좋을까? 4칸이 좋을까?
책에 보면 "가로 들여쓰기: 스페이스 두 개 혹은 네 개를 사용해 만듦"라고 나옵니다.
저는 이번 프로젝트 때 처음으로 2칸으로 써봤는데 4칸으로 다음에는 사용해보려고 합니다.
그 이유를 설명하기 위해 극단적인 케이스를 보여드리겠습니다. ㅎㅎ
리눅스 커널은 탭 사이즈를 스페이스 8개로 권장합니다.

블록이 어디서 시작하고 끝나는지도 더 명확하게 보인다고 합니다.
그리고 사실 이건 아래와 같은 철학을 가지고 있기 때문입니다.
"if you need more than 3 levels of indentation, you’re screwed anyway, and should fix your program"
저는 이번에 프로젝트를 2칸으로 해보고 깨달았습니다. 리눅스 커널처럼 8칸은 필요하지 않고 4칸이 적당한 것 같습니다.
저도 2칸으로 하니깐 depth가 조금밖에 차이가 안 나서 테스트코드랑 다른 코드를 짤 때 헷갈렸습니다.
그리고 여러 level로 높아져도 티가 별로 안 나서 잘 못 된 점을 알아채기 위해서라도 4칸이 적당한 것 같았습니다.
주로 2칸을 쓰는 것 같던데 다른 Node진영 백엔드 분은 몇 칸을 선호하시는지 궁금하네요!!
함수의 위치
- 헬퍼 함수를 사용하는 코드 위에서 헬퍼 함수를 모아 선언하기
- 코드를 먼저, 함수는 그 다음에 선언하기
- 혼합: 코드 바로 위에서 필요한 헬퍼 함수 그때그때 선언하기
책에서도 사람들이 무엇을 하는지를 생각하며 코드를 읽기 때문에 2번이 자연스럽다고 합니다.
저도 동일하게 2번을 선호합니다.
2번이긴 한데.. 함수가 먼저 올 수도 있다고 생각합니다.
동료가 어떤 소스코드을 열었을 때 그 파일에서 원하는 것이 있을 겁니다. 그 사람이 봤으면 하는 부분이 먼저 보여야 한다고 생각합니다.
예를 들어서, 백엔드에서 main.ts 파일을 열면 bootstrap하는 부분을 기대할 것이기 때문에 그 부분 제일 먼저 보여야 할 것입니다.
// 제가 짠 백엔드 코드 main.ts // https://github.com/SWM-FIRE/modoco-backend/blob/1df1d7cddbfb09fd44ead9d0b52bc8fa189e213a/src/main.ts import { NestExpressApplication } from '@nestjs/platform-express'; // import들 생략 ... /** * bootstrap server */ async function bootstrap() { // create express application const app = await createServer(); // get config service const configService = app.get(ConfigService); const authService = app.get(AuthService); // pre init server preInitServer(app, configService); // connect to redis const redisIoAdapter = await connectRedis(app, configService, authService); // init server return await initServer(app, redisIoAdapter, configService); } /** * Create nestExpressApplication application * @returns {Promise<NestExpressApplication>} NestExpressApplication app */ async function createServer(): Promise<NestExpressApplication> { return await NestFactory.create<NestExpressApplication>(AppModule); } // 함수 선언들 생략 ... /** * initialize server * @param {NestExpressApplication} app NestExpressApplication app * @param {RedisIoAdapter} redisIoAdapter redis adapter * @param {ConfigService} configService config service */ async function initServer( app: NestExpressApplication, redisIoAdapter: RedisIoAdapter, configService: ConfigService, ) { const PORT = configService.get<number>('PORT'); const API_VERSION = configService.get<string>('API_VERSION'); await app .useWebSocketAdapter(redisIoAdapter) .useGlobalPipes(new ValidationPipe({ whitelist: true })) .useGlobalInterceptors(new NewrelicInterceptor()) .setGlobalPrefix(`/api/${API_VERSION}`) .listen(PORT); // starts listening for shutdown hooks app.enableShutdownHooks(); // subscribe to shutdown hook app.get(ShutdownService).subscribeToShutdownApp(() => app.close()); return PORT; } // call bootstrap bootstrap() .then((port) => logger.log(`Server listening on port ${port}`)) .catch((error) => logger.error(error.message, error));
저는 eslint와 prettier를 같이 사용합니다.
// .eslintrc.json { "env": { "node": true, "jest": true, "es2021": true }, "extends": [ "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended" ], "overrides": [], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, "plugins": ["@typescript-eslint"], "rules": { "@typescript-eslint/interface-name-prefix": "off", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-unused-vars": "off" }, "ignorePatterns": ["node_modules", "test", "dist", "**/*spec.ts"] }
// .prettierrc { "singleQuote": true, "trailingComma": "all" }
eslint와 prettier의 충돌을 막기 위한 extends 설정도 있고 타입스크립트에 대한 것도 정의되어 있습니다.
그리고 off로 끈 rules들은 (특히 reflection을 쓰는) 프레임워크나 typeorm을 사용하는 할 때 불편해서 끈 것들이 대부분입니다.
주석
주석
ko.javascript.info
JSDoc과 "주석 없이 코드 자체만으로 코드가 무슨 일을 하는지 쉽게 이해할 수 있어야 합니다" 이 말 하나로 정리되는 것 같습니다!
주석뿐만이 아니라 리팩터링에 관한 내용도 많이 나오네요.
코드 자체의 가독성을 높이는 리팩터링 기법은 "리팩터링 - 마틴 파울러" 책에 잘 나타나있습니다.
테스트 코드를 안 짰더라도 참고할 만한 부분이 있습니닷,,,! 리팩터링 2 책이 JS기반으로 나와서 읽는데 문제 없을 겁니다.
리팩터링 2판 - YES24
개발자가 선택한 프로그램 가치를 높이는 최고의 코드 관리 기술마틴 파울러의 『리팩터링』이 새롭게 돌아왔다.지난 20년간 전 세계 프로그래머에게 리팩터링의 교본이었던 『리팩토링』은,
www.yes24.com
함수 추출 등 많은 기법이 담겨있습니다.
그리고 마지막에 이 말이 공감이 되네용 ㅎㅎ..
직감에 반하는 미묘한 동작을 수행하는 코드가 있다면 주석을 달아주는 것이 좋다.
실력이 부족해서인지.. 가끔 저런 코드를 짤 수 밖에 없을 때가 오는데 그때는 적어주는 것이 좋을 것입니다.
말고도 테스트 코드를 짜면 자연스럽게 코드가 정돈됩니다.
테스트 코드를 짜지 않으면 테스트가 절대 불가능한 코드들이 나오고는 하는데 이런 코드들이 정돈이되면서 자연스럽게 쪼개지거나 의존성이 밖으로 나옵니다.
테스트 코드가 있어야 제대로된 리팩터링이 가능해집니다. 테스트 코드에 관한 중요성은 저 위에 있는 리팩터링 2 책에도 많이 설명해줍니다.ㅎㅎ
닌자 코드
닌자 코드
ko.javascript.info
끔찍한 코드들이 많네요 ㅎㅎㅎㅋㅋㅋㅋ.
학부생 초반에 백준 문제를 풀면서 많이들 착각했던 부분이 있습니다. 짧은 코드, 변수명 글자 하나, 한 함수에 몰아넣기 등등
조심해야 할 것입니다..!!
테스트 자동화와 Mocha
테스트 자동화와 Mocha
ko.javascript.info
백번 강조해도 부족한 테스트 코드!ㅎㅎ
JavaScript 입문 책에는 테스트 코드에 관한 내용이 스킵되고는 하는데 이런 내용도 있다는 것이 좋네용..!
테스트 코드를 한번도 안 짜보셨다면 한번은 꼭 읽어볼만한 내용입니다.
여기 책에서 예시로 사용하는 Chai 라이브러리가 BDD/TDD Assertion 라이브러리입니다.

그래서 그런지 BDD로 내용이 진행됩니다.
실제로 테스트 코드는 다른 비개발자 직군의 사람들과 의사소통할 때도 좋은 도구입니다.
그냥 코드를 보여주는 것보다 테스트코드를 보여주면서 설명해주면 더 낫다고 합니다.
어떻게 도움이 되는지 한번 읽어보세요!
저는 대표적인 Jest와 Mocha를 비교해보고 넘어가겠습니다 ㅎㅎ.
보통 JavaScript 진영에서는 테스트 코드를 짤 때 유명한 프레임워크로 다음과 같은 것이 입니다.
- Jest (강력한 Mocking 기능으로 TOP 1)
- Mocha (+ Chai)
- Cypress
- 등
여러 선택지가 있습니다. 프론트엔드에서는 dom 검사를 위해서 react-testing-library 등을 함께 쓰던군영.
Jest는 기능이 강력한 대신 느립니다. 나중에 테스트가 쌓이면 매번 몇 초 동안 기다려야 하기 때문에 답답할 수 있습니다.
대신 zero config를 추구하기 때문에 특별한 설정 없이 바로 시작할 수 있습니다.

환경을 Mocha + Chai로 세팅해봤던 저장소입니다.
GitHub - IamGroooooot/ts-goos-tdd
Contribute to IamGroooooot/ts-goos-tdd development by creating an account on GitHub.
github.com
Mocha는 Test 프레임워크입니다. Node나 브라우저 상으로 동기적이거나 비동적인 코드를 테스팅할 수 있게 해줍니다.
테스트코드를 짜보셨다면 익숙할 describe, it, before, after 와 같은 함수 등을 제공해주고 test coverage도 계산해줍니다.
보통 여러 Assertion을 추가적으로 쓰기 위해서 Chai라는 라이브러리와 같이 씁니다.
Chai로 expect(myVariable).to.equal(111)와 같은 assertion을 작성할 수 있게됩니다.
얘가 Jest에 비해 몇 배 더 빠릅니다.
폴리필
폴리필
ko.javascript.info
이전 장에서 transpiler에 대한 설명을 했습니다.
babel과 같은 transpiler는 내가 사용한 최신 문법을 구버전 문법으로 변환시켜줍니다.
polyfill은 변경됐거나 새로운 표준을 준수할 수 있게 기존 함수의 동작 방식을 바꿔주는 것을 말합니다.
예를 들어서, 어떤 문법을 지원하지 않는 구버전 브라우저에서도 그대로 사용하고 싶은 경우 polyfill로 사용할 수 있습니다.
fetch가 많은 브라우저에서 아직 지원하지 않는다고 가정합시다. 그런데 사용하고 싶으면 지원되지 않는 브라우저에서는 fetch를 위한 polyfill로 실행되도록 하는 겁니다.
4장 객체:기본
객체
객체
ko.javascript.info
오직 한 가지의 데이터만 담을 수 있는 자료형은 '원시형(primitive type)'이라 부릅니다.
객체형은 원시형과 달리 다양한 데이터를 담을 수 있는 자료형입니다.
객체 만드는 법
// 객체 생성자 let obj1 = new Object(); // 객체 리터럴 let obj2 = {}; // 여러 property를 가진 객체 생성 let ob3 = { a: "a value", b: 1234 };
객체 가지고 놀기
// 여러 property를 가진 객체 생성 let obj = { a: "a value", b: 1234 }; console.log(obj.a); console.log(obj.b); // a property 변경 obj.a = false; console.log(obj.a); // a property 삭제 delete obj.a; console.log(obj.a);
복수의 단어로 된 프로퍼티
// 여러 property를 가진 객체 생성 let obj = { a: "a value", b: 1234, "i am groot": true }; console.log(obj["i am groot"]); // 불가능한 경우 const key = "i am groot"; console.log(obj.key) // undefined // obj["i am groot"] 삭제 delete obj["i am groot"]; console.log(obj["i am groot"]);
계산된 프로퍼티(computed property)
property의 이름을 변수로부터 가져올 수 있다.
let myProperty = "bbb"; let obj = { [myProperty + "Prop"]: 5, // property 이름을 myProperty 값으로부터 동적으로 가져온다 }; console.log(obj.bbbProp); // 5
프로퍼티 값 단축 구문(property value shorthand)
const name = "Juhyeong"; const nickname = "Groot"; // 결과는 동일하다 console.log({ name, nickname }); console.log({ name: name, nickname: nickname });
프로퍼티 값은 문자열로 자동 형 변환된니다. (심볼형은 예외입니다)
let obj = { 0: "test" }; // == let obj = { "0": "test" };
프로퍼티 존재 여부 체크하기
let obj = {}; console.log(obj.aaa !== undefined); console.log("aaa" in obj); // in만 가능한 경우 let obj2 = { aaa: undefined }; console.log(obj2.aaa !== undefined); // 원하는대로 작동 X console.log("aaa" in obj2);
for ... in, 프로퍼티엔 순서가 있을까?
정수 프로퍼티(integer property)는 자동으로 정렬됩니다.
let obj = { "3": "groot", "2": "am", "1": "i", }; for (let prop in obj) { console.log(prop) // 1, 2, 3 }
그 외의 프로퍼티는 객체에 추가한 순서 그대로 정렬됩니다.
let obj = { "prop3": "groot", "prop2": "am", "prop1": "i", }; obj.prop123 = "hello"; for (let prop in obj) { console.log(prop) // prop3, prop2, prop1, prop123 }
참조에 의한 객체 복사
참조에 의한 객체 복사
ko.javascript.info
객체는 참조에 의해(by reference) 저장되고 복사됩니다. 객체의 데이터 값이 아닌 데이터를 들고 있는 참조(주소)가 복사가 된다는 말입니다.
참조 복사가 아닌 모든 것을 복사하고 싶다면 Deep copy를 찾아보세요.
https://www.builder.io/blog/structured-clone
가비지 콜렉션
가비지 컬렉션
ko.javascript.info
자바스크립트는 도달 가능성(reachability) 이라는 개념을 사용해 메모리 관리를 수행합니다.
객체는 도달 가능한 상태일 때 메모리에 남습니다.
참조된다고 해서 도달 가능한 것은 아닙니다. 서로 연결된 객체들도 도달 불가능할 수 있습니다.
자바스크립트가 메모리 누수가 날 때는 주로 Closure 때문에 발생합니다. Closure 사용시에 주의가 필요 합니다.
Closure는 lexical environment도 가져가는데 이 부분을 조심하셔야 합니다.
자세한 내용은 다음 글을 참고해보세요.
https://blog.logrocket.com/escape-memory-leaks-javascript/#closures
메서드와 this
메서드와 this
ko.javascript.info
skip
new 연산자와 생성자 함수
new 연산자와 생성자 함수
ko.javascript.info
skip
옵셔널 체이닝 ?.
옵셔널 체이닝 '?.'
ko.javascript.info
옵셔널 체이닝(?.)은 앞에 있는 평가 대상이 undefined나 null이면 평가를 멈추고 undefined를 반환합니다.
다른 언어에서도 ?. 오른쪽에 있는 부가 동작은 ?.의 평가가 멈췄을 때 더는 일어나지 않는 단락 평가를 활용해서 간단하게 null exception error를 만는 용도로 사용하고는 했습니다.
책에도 적혀있지만 남용하면 어디서 터지는지 잡기 어려워져서 조심해야 합니다.
(프론트분들 예외) 대충 터지면 ? 남용하는 분들도 많이 봤는데ㅎㅎ 에러 처리 잘해야 합니다!
?.은 연산자가 아닙니다.
문법 구조체(syntax construct)이기 때문에 아래와 같은 코드가 가능합니다.
let hello = { world() { console.log("hello, world!"); } } let goodbye = {}; hello.world?.(); // hello, world! goodbye.world?.();
심볼형
심볼형
ko.javascript.info
자바스크립트는 프로퍼티의 키로 문자열 말고도 Symbol형도 허용을 합니다.
이러한 심볼형은 유일한 식별자를 만들기 위해서 사용됩니다.
저는 자바스크립트 내부적으로 간단하게 어떤 객체를 구별해야 했을 때 쓴 기억이 있습니다. 따로 id를 별도로 카운팅해서 설정하는 대신 심볼을 이용해서 객체 구별하도록 했습니다.
심볼은 다음과 같이 생성해서 사용할 수 있습니다.
// 심볼 생성 let id1 = Symbol(); // 설명이 있는 심볼 생성 let id2 = Symbol("id"); console.log(id2.description) // id // 심볼을 이용한 객체 생성 let obj = { [id1]: "unique1", [id2]: "unique2" }; console.log(obj[id2]); // unique2 // 심볼은 설명과 상관 없이 유일합니다. console.log(Symbol("id") == Symbol("id")); // false
설명은 단지 디버깅 용도로 라벨과 같은 역할을 합니다. 모든 symbol은 생성될 때마다 유일합니다.
심볼을 이용하면 프로퍼티를 숨길 수 있습니다.
숨김 프로퍼티는 외부 코드에서 접근이 불가능하고 값도 덮어쓸 수 없습니다.
그렇기 때문에 외부 써드 파티로부터 객체에 우리가 새로운 프로퍼티를 추가하고 싶으면 사용하기 좋습니다.
// 서드 파티에서 받아온 객체에는 이미 id가 있다 const user = { id: 1577, name: "Groot" }; // ------------------------------------ // // 우리가 원하는 프로퍼티를 추가 const ID_SYMBOL = Symbol("id"); user[ID_SYMBOL] = 1; // ------------------------------------ // // 서드 파티 객체의 id console.log(user.id); // 1577 // 내가 서드 파티 객체에 추가한 id console.log(user[ID_SYMBOL]); // 1
위와 같이 심볼로 이름 충돌을 예방할 수 있습니다.
심볼은 for ... in 에서 배제됩니다.
hiding symbolic property라 불리는 원칙 덕분에 외부에서 심볼형 키를 가진 프로퍼티에 접근하지 못하게 되어 있습니다.
하지만 객체 복사를 할 때는 심볼을 포함합니다.
let ID_SYMBOL = Symbol("id"); let user = { [ID_SYMBOL]: 1 name: "groot", }; for (let key in user) { console.log(key); // name } let clone = Object.assign({}, user); console.log(clone[ID_SYMBOL]); // 1
전역 심볼
애플리케이션 전역에서 심볼을 사용하기 위해 global symbol registry가 있습니다.
Symbol.for(키)를 통해 전역 레지스트리 안의 심볼을 읽거나 (없는 경우) 새로 생성할 수 있습니다.
// id key로 새로운 심볼이 생성 후 전역 레지스터리에 등록 const ID_SYMBOL = Symbol.for("id") // Symbol.for("id")을 통해 기존에 있는 id key값을 가진 심볼이 반환됩니다. console.log(ID_SYMBOL === Symbol.for("id")); // true console.log(ID_SYMBOL.description) // id
Symbol.keyFor(심볼)을 통해 반대로 key값을 찾을 수도 있습니다.
// id key로 새로운 심볼이 생성 후 전역 레지스터리에 등록 const ID_SYMBOL = Symbol.for("id") // 내 키 값이 뭐였지? // 레지스터리에 있는 경우 console.log(Symbol.keyFor(ID_SYMBOL)); // id // 레지스터리에 없는 경우 (description은 심볼을 구분하는 것과 아무 상관이 없습니다~) console.log(Symbol.keyFor(Symbol("id"))); // undefined
자바스크립트 내부에서 사용되는 심볼로 system symbol도 있습니다. 그 중의 대표적인 toPrimitive을 아래에서 설명합니다.
객체를 원시형으로 변환하기
객체를 원시형으로 변환하기
ko.javascript.info
Symbol.toPrimitive을 사용하면 객체가 형 변환을 할 때 어떤 값으로 바꿀지 설정할 수 있습니다.
* 객체는 논리 평가 시 무조건 true를 반환합니다.
객체의 형변환 hint로 결정됩니다. hint에 따라 어떤 값으로 변할지 선택됩니다.
hint는
- "string": 문자열을 기대하는 연산을 수행할 때
- "number": 수학 연산을 적용하려 할 때
- "default": 애매할 때
이 세가지 값 중 하나입니다.
Symbol.toPrimitive는 무조건 원시형을 반환해야 합니다.
예를 들어서 다음과 같이 쓸 수 있습니다.
let user = { name: "Groot", money: 1000, [Symbol.toPrimitive](hint) { if (hint === "string") return name; else return money; } }; console.log(user); // Groot console.log(+user); // 1000
toString과 valueOf를 써서도 구현할 수 있습니다.
이 메서드들은 Symbol.toPrimitive가 없으면 자바스크립트가 호출합니다.
- hint가 "string"이면 toString -> valueOf
- hint가 "number"나 "default"이면 valueOf -> toString
순으로 호출됩니다. 만약 하나라도 호출된다면 뒤의 함수는 호출하지 않습니다.
이 메서드들도 원시값을 반환해야 하지만 아닌 경우 무시되며 아래와 같은 기본 동작을 합니다.
- toString은 "[object Object]"을 반환합니다.
- valueOf는 객체 자신을 반환합니다.
예를 들어서 다음과 같이 쓸 수 있습니다.
let user = { name: "Groot", money: 500, toString() { // hint가 "string"인 경우 return this.name; }, valueOf() { // hint가 "number"나 "default"인 경우 return this.money; } }; console.log(user); console.log(+user);
책에 따르면 실무에선 obj.toString()만 구현하고는 한다고 합니다. 주로 로깅이나 디버깅 용도로 많이 쓴다합니다.
저도 C#과 Java에서 최고 조상 클래스인 Object에서 로깅이나 디버깅하는 용도로 toString을 overriding해서 많이 쓴 기억이납니다.
참고
출처
댓글
이 글 공유하기
다른 글
-
모던 JavaScript 튜토리얼 파트 1 :: 6장 "함수 심화학습" 정리
모던 JavaScript 튜토리얼 파트 1 :: 6장 "함수 심화학습" 정리
2023.01.16모던 JavaScript 튜토리얼 파트 1의 6장을 읽으면서 정리하는 글입니다. 1. 재귀와 스택 재귀와 스택 ko.javascript.info 자바스크립트는 재귀 함수의 깊이를 제한한다. (엔진에 따라 다르지만 만개 정도는 확실히 허용한다고 합니다.) function A(i) { i = i - 1; if (i < 0) return 0; return A(i); } const result = A(10_000); // 허용! const result = A(10_956); // 허용! const result = A(10_957); // Uncaught RangeError: Maximum call stack size exceeded 크롬에서 간단하게 검사툴로 돌려보니깐 10,956까지만 허용하네용. 꼬리 재귀 … -
모던 JavaScript 튜토리얼 파트 1 :: 5장 "자료구조와 자료형" 정리
모던 JavaScript 튜토리얼 파트 1 :: 5장 "자료구조와 자료형" 정리
2023.01.09 -
모던 JavaScript 튜토리얼 파트 1 :: 1장, 2장 정리
모던 JavaScript 튜토리얼 파트 1 :: 1장, 2장 정리
2022.12.26https://ko.javascript.info/ 를 읽으며 정리하는 글입니다. 이 책을 천천히 정리하면서 제가 알고 있는 내용을 함께 적어봅니당. 1장 소개 자바스크립트란? "자바스크립트는 ‘웹페이지에 생동감을 불어넣기 위해’ 만들어진 프로그래밍 언어"입니다. 보통 웹페이지의 HTML 안에 작성하거나 불러와서 웹페이지를 불러올 때 스크립트가 자동으로 실행됩니다. 자바스크립트는 자바스크립트 엔진에서 돌아간다. 브라우저엔 '자바스크립트 가상 머신'이라는 불리는 엔진이 내장되어있고 대표적으로 크롬에서 사용하는 V8 엔진이 유명합니다. 책에서는 자바스크립트는 안전한 프로그래밍 언어라고 표현합니다. 브라우저를 대상으로 만든 언어이기 때문에 메모리나 CPU 같은 저수준 영역의 조작을 허용하지 않습니다. 인터넷에서… -
발전한 자바스크립트와 현재 jQuery의 위치
발전한 자바스크립트와 현재 jQuery의 위치
2021.07.10이틀 전에 '제이쿼리는 왜 FD 로드맵에서 삭제 되었을까?'라는 글을 재밌게 읽었습니다. 문득 jQuery의 흔적을 자주 볼 수 있는 인트라넷에 이 글과 제가 개발 공부를 하면서 느낀 JavaScript와 jQuery에 관해서 쓰면 좋을 거 같아서 남겨봅니다. 주의 부족한 경험과 기억에 의존해서 적는 글이라 틀린 부분이 있을 수 있습니다. 오류나 틀린 부분이 있다면 지적 부탁드립니다! jQuery가 개발되기 전의 웹 초창기(1995~1996) 웹 브라우저 jQuery가 개발되기 전의 JavaScript는 브라우저 제조사 별로 표준이 달라서 같은 JavaScript 코드라도 어떤 브라우저에서는 동작하지만 어떤 브라우저에서는 안 돌아가는 경우가 많았습니다. 그래서 개발자에게 JavaScript는 손이 여러모…
댓글을 사용할 수 없습니다.