변수
자바스크립트는 C나 Java외는 다르게 변수를 선언할 때 데이터 타입을 미리 지정하지 않는다.
다시 말해, 변수에 할당된 값의 타입에 의해 동적으로 변수의 타입이 결정된다.
이를 동적 타이핑이라 하며 자바스크립트가 다른 프로그래밍 언어와 구별되는 특징 중 하나이다.
// Number
let num1 = 1001;
let num2 = 10.50;
// String
let string1 = 'Hello';
let string2 = "World";
// Boolean
let bool = true;
// null
let foo = null;
// undefined
let bar;
// Object
let obj = { name: 'Lee', gender: 'male' };
// Array
let array = [ 1, 2, 3 ];
// function
let foo = function() {};
Script 태그의 위치에 따른 결과 , Script 태그의 attribute
head태그안에 Script 태그가 존재하는경우
1. parsing HTML
브라우저가 html코드를 한줄씩 분석하여 css와 결합하여 DOM을 만들어낸다.
[문서 객체 모델(DOM)은 메모리에 웹 페이지 문서 구조를 표현함으로써
스크립트 및 프로그래밍 언어와 페이지를 연결합니다.]
2. fetching js
브라우저가 html을 parsing 하다가 <script> 태그에 도달하면
자바 스크립트를 가져온다.
3. executing js
가져온 자바 스크립트를 실행시킨다.
이렇게되면 js가 클경우 html을 불러올때까지 시간이 소요된다.
[ 사용자가 페이지의 컨텐츠를 볼 때까지 시간이 걸린다. ]
Body태그 끝에 Script 태그가 존재하는경우
이렇게 한 경우 browser가 script태그를 만날때까지 html을 쭉 파싱하기 때문에
html의 준비가 다 된 상태일것이다. [ 사용자가 페이지의 컨텐츠를 빨리 볼 수 있다. ]
하지만 html이 자바스크립트의 의존적인 html이라면 ( 동적으로 데이터가 필요하는 등)
사용자는 정상적으로 html이 동작하기 전까지 ( fetching, executing js가 완료될때까지) 기다려야한다.
Head 태그안에 Script 태그 존재, Script 태그에 async 속성 존재
asyn는 boolean 타입이고 기본값은 true이다.
asyn 속성이 존재하면 browser는 html을 pasing 하면서 동시에 병렬로 js를 fetching 하기 시작한다.
js를 다운로드하는것이 완료되면 parsing을 멈추고 js를 실행한다.
실행이 끝나면 나머지 html을 parsing한다.
body태그 끝에 script를 사용하는것보다는
parsing 도중에 js를 다운로드 하기 때문에 다운로드 받는 시간을 절약 할 수 있다.
하지만 여전히 자바스크립트를 실행하는 도중에는 parsing을 멈추기 때문에
사용자에게 페이지를 보여주는데 시간이 소요된다.
여러개의 자바스크립트 파일이 존재할시 자바스크립트 파일을 다운이 완료되면 즉시 파싱을 멈추고 자바 스크립트를 실행하게 된다. 만약 자바스크립트가 순서에 의존적이라면 원하는 순서대로 진행될수 없어 문제가 될 수 있다.
[다운받는 대로 실행이 되기 때문]
head + defer
script 태그에 defer 속성이 존재한다면 브라우저는 fetching js 를 진행하고 나머지 html를 parsing한다.
(자바스크립트를 다운만 받고 , 쭉 파싱을 진행한다.)
html parsing이 끝난 이후 다운받은 자바스크립트를 실행한다.
html parsing을 먼저하게 되고 즉 사용자에게 페이지를 보여주고 나서 바로 자바스크립트를 실행하기 때문에
사용자에게 대기시간없이 완전한 페이지를 보여줄수있게된다.
defer 같은 경우 html parsing과 동시에 fetching(자바스크립트 다운로드)을 진행한다.
fetching이 끝나고 자바스크립트를 실행하지않고 html의 parsing까지 기다린다.
parsing이 완료되면 자바스크립트를 실행하게된다.
html이 parsing이 먼저 다 되므로 사용자는 페이지를 눈으로 볼수 있고
그 이후 바로 자바스크립트가 실행되므로 정상적인 페이지 동작을 볼 수 있다.
사용자의 대기시간이 없다.
또한 원하는 자바스크립트 순서를 지킬면서 실행될 수 있다.
즉 defer옵션이 가장 안전하고 효율적이다.
'use strict';
타입스크립트를 사용할때는 상관없지만 순수 자바스크립트를 사용할때는
자바 스크립트 파일 제일 윗부분에 'use strict'; 를 선언하는게 좋다.
선언되지않은 값을 할당한다던지, 사용한다던지
호이스팅으로 인한 문제들을 사전에 막기위해 컴파일 에러를 발생시킨다.
템플릿 리터럴은 내장된 표현식을 허용하는 문자열 리터럴
백틱 ` 을 사용한다.
let a = 'hi';
console.log(`String ${a} : ${typeof a}
'''""" hihihi
띄어쓰기23123
`);
백틱안에서 ${}를 이용하여 변수같은걸 출력하고
`` 안에서는 한줄개행도 자유롭고 ' " 와 같은 문자도 자유롭게 사용가능하다.
== loose eqaulity , === strict equality
stringFive는 '5' 가 담겼으므로 String 이고
numberFive는 5가 담겼으므로 Number일텐데
==(loose) 은 타입을 변경해서 검사하기 때문에 결국 같은 값으로 취급된다.
===(Strict) 인 경우 타입 변경을 안하고 검사하기 때문에 false로 나온다.
0,''(빈문자),null 은 false로 취급 되므로 false와 loose 비교는 같다고 나온다.
=== strict 비교는 타입이 다르므로 false로 나온다.
null은 undefined와 loose 비교는 true로 나온다.
function
자바스크립트는 변수에 함수를 담을 수 있다.
자바스크립트에서 함수는 객체이다.
let hi = function (a) {
console.log(a);
return 130;
}
let number = hi(10);
사용법은 변수명을 이용한다.
매개변수에 대한 기본값을 설정 할 수 있다.
function hi2(message, from = 'unknown') {
console.log(`message : ${message} from ${from}`);
}
hi2('ggggg');
기본값을 설정하지않고 from의 값을 넣지않는다 undefined로 출력된다.
rest parameters
function printALL(...args) {
for (let i = 0; i < args.length; i++) {
console.log(args[i]);
}
}
printALL('dream', 'coding', 'ellie');
rest parameter는 배열형식으로 전달되어 args에 들어간다.
for (const arg of args) {
console.log(arg);
}
of를 이용 할 수도 있다 자바의 개선된 for문 처럼
args.forEach((arg) => console.log(arg));
또는 이렇게 이용할 수 있다.
자바의 람다식처럼 ( 하지만 -> 가 아닌 =>이다.)
function printALL(...args) {
let message = 'hello';
args.forEach((arg) => console.log(arg));
function printAnother() {
console.log(message);
} //함수안에 함수를 선언할 수있다.
printAnother(); // 내부에서 사용하거나
return printAnother();// 반환해줄수있다.
// return undefined 이게 숨어있다.
}
const print = function () { // 이렇게 함수의 이름이 없는것을 익명함수라고 한다.
console.log('print');
};
자바스크립트에서 함수도 객체이므로 변수에 담을 수 있다.
const print = function printtt() { // 이렇게 이름이 있는것은 name function
//디버깅할때 함수 이름이 나오게 하기 위함
//또는 함수내부에서 자기 스스로 함수를 호출하기위함
// printtt();
console.log('print');
};
print(); // 담은 변수 이름으로 실행하면된다.
printtt2(); // fucntion도 hoisting이 되므로 선언되기전에 사용가능
function printtt2() { // fucntion도 hoisting이 되므로 선언되기전에 사용가능
console.log('print');
}
콜백 함수 callback function
콜백(Callback) 함수는 간단히 말하면 매개변수로 함수 객체를 전달해서
호출 함수 내에서 매개변수 함수를 실행하는 것을 말한다.
function printYes() {
console.log('Yes');
}
function printNo() {
console.log('No');
}
function Quiz(answer, printYes, printNo) {
if (answer === 'love you') {
printYes();
} else {
printNo();
}
}
Quiz('wrong', printYes, printNo);
Quiz('love you', printYes, printNo);
Quiz의 매개변수중 printYes, printNo는 콜백함수이다.
예를 들어 아래 코드와 같이 sayHello() 함수를 호출할때
입력 매개변수로 문자열과 printing 함수 자체를 전달하는 것을 볼 수 있다.
그리고 sayHello() 함수가 실행되면 실행문 안에서 함수가 들은 두번째 매개변수인 callback 을 괄호 () 를 붙여 호출한다.
function sayHello(name, callback) {
const words = '안녕하세요 내 이름은 ' + name + ' 입니다.';
callback(words); // 매개변수의 함수(콜백 함수) 호출
}
sayHello("인파", function printing(name) {
console.log(name); // 안녕하세요 내 이름은 인파 입니다.
});
[매개변수에 함수를 넣을때 그 자리에서 생성해서 넣어줄 수도있다. 자바의 익명함수,람다함수랑 약간 비슷 ]
즉, 콜백 함수란 파라미터로 일반적인 변수나 값을 전달하는 것이 아닌 함수 자체를 전달하는 것을 말한다고 보면 된다.
또한 어차피 매개변수에 함수를 전달해 일회용으로 사용하기 때문에 굳이 함수의 이름을 명시할 필요가 없어 보통 콜백 함수 형태로 함수를 넘겨줄때 함수의 이름이 없는 '익명 함수' 형태로 넣어주게 된다.
[어차피 매개변수 이름으로 함수를 받게되고, 매개변수 이름으로 함수를 실행할 수 있으니까]
function sayHello(name, callback) {
const words = '안녕하세요 내 이름은 ' + name + ' 입니다.';
callback(words);
}
sayHello("인파", function (name) { // 함수의 이름이 없는 익명 함수
console.log(name);
});
arrow function
let simpleFunc = () => console.log('arrow function');
simpleFunc();
let newVar = (a, b) => console.log(a + b);
newVar('10', 20);
즉시 실행 함수 표현식(IIFE, Immediately Invoked Function Expression)
(function hello() {
console.log('hello')
})();
함수를 선언하자마자 바로 사용하고 싶다면
함수 선언을 ()로 묶고 뒤에 ()를 붙여서 바로 함수 실행이 가능하다.
댓글