자바스크립트
1주차-Trello 아키텍처 overview, javascript 기본 돌아가기
자바스크립트 객체지향프로그래밍 별도 페이지
코드 재사용 패턴 가기
자바스크립트 소개와 개요
소개
가장 널리 사용되는 프로그래밍 언어 중 하나
자바와는 아무런 상관이 없다
장점
자바스크립트는 사용하기 쉽다
단점
객체지향적 특성을 가지고 있음
일관성 부족
진정한 객체지향 언어로 보기 어렵다
기능은 제한적
타입 검사가 엄격하지 않음
실행 파일을 생성하지 않음
특징
웹브라우저와 다른 프로그램에 내장되어 사용되는 스크립트 언어
- 이미 성숙한 언어
- 여러 기능을 두루 갖추고 있음
- 충분한 보안 기능을 제공하는 객체기반 언어
- 두가지 측면
스크립팅 언어
객체지향 프로그래밍 언어
브라우저간의 호환성 문제
자바스크립트는 다양한 플랫폼과 환경에서 실행
- 여러 운영체제(Mac OSX, 윈도우, 리눅스, 안드로이드, iOS 등)에서 동작하는 웹페이지 및 프로그램을 개발하는데 사용
- 대부분의 브라우저에 내장되어 있기 때문에 별도의 다운로드나 설치가 필요 없음
- 자바스크립트 언어 보다는 문서 객체 모델(DOM)이 서로 다른 것에서 발생
- 웹페이지의 엘리먼트 중 자바스크립트가 처리하는 부분과 CSS가 처리하는 부분이 중복
- 웹페이지 내의 엘리먼트를 생성 / 제거하고 속성을 변경
- 위에서 속성 변경은 CSS 의 style 속성을 통해서도 가능
- CSS는 웹페이지의 화면 구성뿐만 아니라 엘리먼트의 동작도 정의
- 브라우저에 따라 CSS를 구현하는 방법은 달라질 수 있기 때문에 호환성 문제가 발생
- 자바스크립트는 엘리먼트의 CSS style 속성을 변경 할 뿐
자바스크립트 역사
넷스케이프사가 서버측 기술로 개발한 라이브커넥트 개발
넷스케이프사는 클라이언트측의 스크립트 언어로 라이브 스크립트 개발
자바 프로그램밍 언어의 소유권을 가진 썬사와 제휴를 맺고 자바스크립트이름으로 변경마이크로소프트는 넷스케이프에 대항하기 위행, IE와 VB스크립트 발표
- 넷스케이프와 썬사는 1995년 12월 4일에 자바스크립트를 HTML과 자바를 보완하는 언어로 공표
추후, 마이크로소프트사는 자바스크립트와 유사한 언어인 J스크립트를 발표
브라우저/언어 간의 경쟁은 자바스크립트의 도입을 더욱 촉진
여러 브라우저에서 호환되는 웹페이지를 만들어야하는 부답
호환성 문제를 해결하기 위해 넷스케이프사는 표준화를 추진
첫시도 1996년 자바스크립트의 스펙을 ECMA국제회의에 제출
1997년 ECMA-262를 발표 http://ko.wikipedia.org/wiki/ECMA스크립트 / http://en.wikipedia.org/wiki/ECMAScript
이후, 자바스크립트(J스크립트, ECMA스크립트)를 지원하는 대부분의 회사들은ECMA-262를 지원하는데 동의
현재 HTML5 함꼐 출현한 자바스크립트 표준안을 ECMAScript 5 라 부름 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf (5ed)
- MCMAScript 5
- IE 9 이상에서 지원
- IE 8 이하에서에서는 지원하지 않음
- ECMAScript 5를 지원하지 않는 브라우저에서도 ECMAScript 5의 특정 메서들르 사용하 수 있게 모질라 재단에서 보완 코드 제공
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
자바스크립트 종류
- 모든 웹 브라우저에서 모두 같은 자바스크립트를 사용하지 않음
- 호환성 문제 발생
- 유럽 컴퓨터 제조 협회 European Computer Manufacturer's Association는 자바스크립트를 ECMAScript 이름으로 표준화
- 이 표준을 바탕으로 여러 회사가 자바스크립트를 구현
- 브라우저마다 약간씩 다른 이름의 자바스크립트 사용
- 웹 브라우저나 애플리케이션에 내장된 자바스크립트의 종류
애플리케이션 자바스크립트의 종류 모질라 파이어폭스 자바스크립트 구글 크롬 자바스크립트 인터넷 익스플로러 JScript 오페라 ECMAScriopt 애플 사파리 자바스크립트 마이크로소프트 닷넷 프레임워크 JScript.NET 어도비 플래시와 플렉스 액션스크립트 어도비 아크로벳 자바스크립트
공식 명칭은 ECMAScript
- 자바스크립트라는 용어를 더 많이 사용
자바스크립트 코드의 위치
- 페이지를 로드할 때 동적으로 웹페이지의 컨텐트를 생성하는 경우에은 body 태그 안에 위치시키는게 좋다
- 함수 안에서 정의하고 page 이벤트에 사용되는 자바스크립트 코드는 head 태그안에 위치시키는게 좋다
- body 태그안의 내용을 읽어들이기 전에 로드되기 때문
자바스크립트 파일
- 여러 응용 프로그램에서 재사용할 수 있는 자바스크립트 객체를 위해 별도 파일로 만듬
- 웹페이지 내에서 링크를 걸어줌
- 장점
- 재사용
- 동일한 코드를 수정시 한 파일만 수정
- 스크립트 파일은 웹페이지 내에서 순차적으로 로드
- 예
- <script src="user_make_javascript.js"></script>
자바스크립트 기본
표현식과 문장
용어
- '표현식'
- 값을 만들어내는 간단한 코드
- 123
- 10 + 20 + 30 + 40
- 'SLIPP Study'
- 값을 만들어내는 간단한 코드
- '문장'
- 하나의 표현식도 세미콜로만 찍히면 문장
- 10 + 20 + 30 + 40;
- var slipStudy = 'SLIPP' + ' ' + 'Study';
- alert('안녕!! 슬립!!!');
- 123;
- 하나의 표현식도 세미콜로만 찍히면 문장
키워드
- 현재 모든 브라우저에서 사용하는 28가지 자바스크립트의 키워드
break else instanceof true case false new try catch finally null typeof continue for return var default function switch void delete if this while do in throw with
- 미래에 사용될 가능성 있는 자바스크립트 키워드
abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public
브라우저의 예약어
alert eval location open array focus math outerHeight blur function name parent boolean history navigator parseFloat date image number regExp document isNaN object status escape length onLoad string
위의 키워드를 자바스크립트 프로그램을 작성할 때 사용하지 않기를 권고
- const, debugger 같은 키워드는 이미 일부 브라우저에서 사용
식별자
- 자바스크립트에서 이름을 붙일 때 사용하는 단어
- 식별자는 크게 4가지
구분 단독으로 사용 다른 식별자와 함계 사용 식별자 뒤에 괄호 없음 변수 속성 식별자 뒤에 괄호 있음 함수 메서드 예
alert('Slipp Stuty') 함수 Array.length 속성 input 변수 prompt('메시지', '기본문자') 함수 Math.PI 속성 Math.abs(-123) 메서드
이름짓기
- 규칙
- 키워드를 사용하면 안 된다
- 숫자로 시작하면 안 된다
- 특수 문자는 _과 $만 허용한다
- 공백 문자를 포함할 수 없다
- 예
- 가능
- alpha
- alpha10
- _alpha
- $alpha
- Alpha
- ALPHA
- 불가능
- break
- 키워드
- 123abc
- 숫자가 앞에 나옴
- slipp study
- 공백문자가 있음
- break
- 가능
- 일반적인 관례
- 생성자 함수의 이름은 항상 대문자로 시작
- 객체는 대문자로 시작
- 변수, 인스턴스, 함수, 메서드의 이름은 항상 소문자로 시작
- 이해하기 쉬운 단어 사용
- var interestRate = .75;
- 헝가리식 표기법
- 이름에 데이터 타입을 유추할 수 있는 단서를 넣는 것도 좋은 방법
- var strName = "슬립";
- 이름에 데이터 타입을 유추할 수 있는 단서를 넣는 것도 좋은 방법
- 여러 단어로 만드는 경우
- 캐멀케이스(CamelCase)
- 두 단어가 연결된 부분을 대문자로 하는 것 / 마치 낙타의 등과 같다고 하여 붙여진 명칭
- getName / firstName
- 캐멀케이스(CamelCase)
- 이해하기 쉬운 단어 사용
- var interestRate = .75;
- 헝가리식 표기법
- 이름에 데이터 타입을 유추할 수 있는 단서를 넣는 것도 좋은 방법
- var strName = "슬립"
- 이름에 데이터 타입을 유추할 수 있는 단서를 넣는 것도 좋은 방법
자바스크립트 자바 코딩 스타일과 관례
주석
- HTML 테그 주석
- <!-- 주석 -->
- 자바스크립트 주석
- 한 줄 주석
- // 한줄 주석
- 여러줄 주석
- /*
- 여러줄 주석1
- 여러줄 주석2
- */
- 한 줄 주석
출력
alert()
- alert('안녕? 슬립!');
console
- console.log('Test log');
- IE8 에서는 에러남.
입력
- prompt()
- 문자열을 입력을 할 때 사용
- var input = prompt('Message', '기본값');
- alert (input);
- confirm()
- 불리언을 입력 받을 때 사용하는 함수
- var input = confirm('수락하시겠습니까?');
- alert(input);
- 불리언을 입력 받을 때 사용하는 함수
데이터 타입과 변수
개요
자바스크립트의 관대한 변수 영역
- 데이터타입
- 문자열로 선언한 것을 숫자값으로 사용
- 예
- var n = '1004';
- n + 1004; // 10041004
- n * 2; // 2008
- n / 2; // 502
- n - 2; // 1002
- 데이터타입
- 변수 영역
기본 데이터 타입
string
boolean
number
변수 영역(scope)
- 함수 내에서 지역적
- 전체 자바스크립트 프로그램에 전역적
- 지역 변수
- 선언/초기화한 후에 함수 내부에서 사용
- 함수가 소멸될 때 같이 소멸
- 전역 변수
- 웹페이지에 포함된 자바스크립트의 모든 부분(코드가 페이지에 직접 포함되어 있거나 자바스크립트 라이브러리를 임포트한 경우 모두 포함)에서 접근 할 수 있음
- 아래와 같이 한 줄만으로 변수의 생성/초기화를 동시에 가능
- num_value = 3.5;
- var num_value = 3.5;
- 차이점은 var 키워드의 사용 여부
- 변수를 정의할 때 가급적 var 키워드를 사용하는 것이 좋다
- 전역 변수와 지역 변수의 이름이 동일할 때 충돌을 방지
- 함수 내에서 var 키워드를 사용하면 지역 변수로 간주
- 전역변수 사용시 주의
- 지역변수를 선언할 때는 반드시 'var' 키워드를 사용해서 선언해야 한다
var a = 123; function f() { alert(a); // undefined var a = 1; alert(a); } f(); //----------------- // 전역변수 foo를 test로 설정 var foo = "test"; // if 블럭 안 if (true) { // foo를 'new test'로 설정 var foo = 'new test'; } // alert(foo == "new test"); // 변수 foo를 수정하는 함수 function test() { var foo = "old test"; } // 함수가 호출될 때, foo는 함수 유효 범위 test(); // foo 값은 'new test' alert(foo == "new test"); //---------------- // 문자열 'test'를 담는 전역 유효범위에 속하는 변수 var global = 'test'; // 앞의 전역 변수와 window 객체의 test 프로퍼티가 같다 alert(window.global = global); //---------------- // 함축적인 전역 유효범위 변수 선언 // foo 값을 설정하는 함수 function test() { foo = "test"; } // foo값을 설정하기 위해 호출 test(); // foo는 이제 전역 유효범위 변수 alert(window.foo == "test");
기본 데이터 타입
- 자바스크립트의 기본 데이터 타입은 세가지 string, numeric, boolean
- 문자열, 숫자, 부울 형태로 구분
- number, string, boolean으로 알려진 내장객체
- 앞의 세가지는 원시 값, 뒤의 세가지는 객체
string 데이터 타입
- 문자열 리터럴이란 문자의 연속으로, 홑따옴표(') 또는 쌍따옴표(")를 사용해 시작과 끝을 알려줌
- "This is a string"
- 'But this is also a string'
- ' 와 " 중 어느 것을 사용해도 상관없으나, 시작과 끝의 기호는 일치해야 함
- 따옴표 문자열 내에서 나타내고자 할 때
- var string_value = "This is a 'string' with a quote."
- var string_value = 'This is as "string" with a quote.'
- var string_value = "This is as \"string\" with a quote."
- 변수값은 컨텍스트에 따라 다른 데이터 타입으로 부터 변환
- 문자열을 인자로 받는 함수에 숫자값이나 부울값 변수를 전달하면
- 값을 처리하기 전에 문자열 값으로 자동 변환
- var num_value = 35.00;
- alert(num_value);
- 변수에 + 연산을 할 때에도 문자열 값으로 변환되는 경우도 있다
- +를 사용해 문자열에 비문자열(숫자)을 덧붙인 예
- var num_value = 35.00;
- var string_value = "This is a number:" + num_value;
- 데이터 타입을 명시적으로 변화해주는 함수 사용
- toString()
- 다른 데이터 타입을 String 타입으로 변환했을 때의 결과
toString 변환 테이블
입력 결과 Undefined "undefined" Null "null" Boolean 참인 경우 "true", 거짓인 경우 "false" Number Number 데이터 타입 참고 String 변환이 일어나지 않음 Object 객체에 대한 기본 표현식의 문자열 표현식
- ECMAScript에서는 데이터 타입을 변환하기 전에 toPrimitive함수를 먼저 호출
- toPrimitive 함수는 DefaultValue 객체 메소드를 호출하고
- 그 값이 존재할 경우 결과를 반환
number 데이터 타입
- 자바스크립트에서 숫자란 부동소수점 수
- 소수점이 없거나, 소수점 이하 수가 없는 경우에는 10진 정수로 취급
- 숫자 범위
- -2^53 ~ 2^53
- 정수
- -1000
- 0
- 2534
- 보동소수점 수
- 0.3555
- 144.006
- -2.3
- 442
- 19.5e-2
- 일부 함수는 -2^31 ~ 2^31 까지의 범위 내에서만 제대로 동작
- -2,147,483,648 ~ 2,147,483,648
- 수에는 + 무한대와 - 무한대의 두 개의 특별한 수가 존재
- Infinity, -Infinity 로 표기
- 자바스크립트에서는 수치 오버플로우가 발생하면 +무산대 값을 반환
- 10진수 표기법외 8진수 및 16진수 표기법도 사용
- 16진수
- 0x를 수치값 앞에 붙여서 표기
- -0xCCFF
- 8진수
- x를 빼고, 0만 붙여 표기
- 0526
- 16진수
- 문자열이나 부울값도 숫자로 변환
- parseInt, parseFloat
- 문자열 속에 숫자가 아닌 값이 나타날 때까지 수의 값을 반환
- parseInt("20abc")
- 20
- parseFloat("1.45inch")
- 1.45
- parseFloat("1.23e-2")
- 0.0123
- parseInt("20abc")
- 8진수, 16진수 변환
- parseInt("0266",8)
- 182
- parseInt("0x5F",16)
- 96
- parseInt("0266",8)
- 숫자값으로의 변환
입력 결과 Undefined NaN Null 0 Boolean 참인 경우 1이고, 그 외의 경우는 0 Number 그대로 String number 데이터 참고 Object 객체의 기본 표현을 숫자로 표현
- isFinite함수를 사용해서 변수값이 무한대인지르 검사
- 함수는 변수값이 무한대(infinity)이거나 숫자가 아닌 경우(NaN)에 false를 반환하고
- 그 외의 경우에는 true 반환
- isFinite("abc")
- false
- isFinite("120")
- true
- isFinite("abc")
boolean 데이터 타입
- 두 가지 값
- true
- false
- toBoolean 변환 테이블
입력 결과 Undefined false Null false Boolean 그대로 Number 숫자값이 0 또는 NaN인 경우에는 false, 그 외의 경우는 true String 문자열이 비어있을 경우에는 false이고, 그 외의 경우는 true Object true - 52 > 273 - false
- 52 < 273 - true
- 비교 연산자
연산자 설명 >= 좌변이 우변보다 크거나 같다 <= 우변이 좌변보다 크거나 같다 > 좌변이 크다 < 우변이 크다 == 좌변과 우변이 같다 != 좌변과 우변이 다르다
'가방' > '하마' - false
- 가방이 하마보다 앞쪽에 있으므로 false
- '가' == '가' - true
- true > false - true
- 1 > 0
if (boolean 표현식) { 불리언 표현식이 참일 때 실행할 문장 }
alert(Boolean(0)); alert(Boolean(NaN)); alert(Boolean('')); alert(Boolean(null)); alert(Boolean(undefined)); alert(!!0)); alert(!!NaN); alert(!!''); alert(!!null); alert(!!undefined);
논리 연산자
연산자 설명 ! 논리 부정 연산자 && 논리곱 연산자 || 논리합 연산자
Null과 Undefined
- null 과 undefined 의 경계 불분명
- null 변수란 정의되지 않은 변수
- 아래와 같이 var키워드를 사용해서 선언되지도 않았고, 함수의 매개 변수로 넘겨준 적도 없는 경우
- alert(sValue)
- undefined - 아래와 같이 변수가 선언되고 초기화되지 않은 경우
- var sValue;
- alert(sValue);
- 변수를 처음 선언할 때 초기화도 같이 해주면 null도 undefined도 아닌 상태
- var sValue = "";
- 변수의 선언 후에 초기화 확인 방법
- if (sValue) .... // null이 아니고 초기화 된 변수라면, 그 결과가 true다. 그외의 경우는 false 다
- 아래 참고
- false
- if (sValue) //
- false
- var sValue;
- if (sValue) //
- true
- var sValue = 1;
- if (sValue) //
- 변수값이 null인지를 알아보기 위해 다음과 같이 null 키워드를 사용
- if (sValue == null)
- false
- 자바스크립트에서는 변수 선언을 한 경우라도 초기화하지 않으면 undefined라는 점을 기억
- 함수의 매개 변수로 넘겨주었을 때,
- null의 경우는 에러를 내는 반면
- undefined의 경우는 에러를 내지는 않는다
- alert(sValue); //
- -
- var sValue;
- alert(sValue); // 에러는 아니지만, "undefined"라고 출력한다
- 함수의 매개 변수로 넘겨주었을 때,
- NaN(Not a Number : 숫자가 아님)
- 문자열이나 부울 변수를 숫자로 바꿀수 없는 경우에 NaN 으로 간주
- var nValue = 1.0;
- if (nValue == 'one') // 두번째 피연산자가 NaN 이므로 false 다
- NaN 인지 테스트하기 위해 isNaN 함수 사용
- if (isNaN(sValue)) // 문자열이 묵시적을 ㅗ숫자로 변화될 수 없다면 true를 반환
- null값은 정의되지 않은 값이므로 NaN 이 된다
- 문자열이나 부울 변수를 숫자로 바꿀수 없는 경우에 NaN 으로 간주
상수
선언 후에 값 변경을 원치 않는 경우 사용
const 키워드 사용해서 선언상수는 어떤 값을 가질 수 있지만, 나중에 변경이 불가능
- const STUDY_MEMBER = 16;
상수도 변수와 마찬가지로
전역 상수
지역 상수
자료형 검사
- 자료형 확인
- typeof 연산자 사용
alert(typeof ('String')); // string alert(typeof (273)); // number alert(typeof (true)); // boolean alert(typeof (function () {})); // function alert(typeof (typeof({})); // object alert(typeof (beta)); // undefined
연산자와 구문
- 자바스크립트 구문
- 배정문
- 함수 호출문
- 조건문
- 반복문 등
자바스크립트 구문의 형식
- 세미콜론( ; )을 종료자로 사용
- 모든 구문에 반드시 종료자를 붙일 필요는 없다
- 한 구문이 그 자체로 완성된 하나의 구문이고,
- 한 줄의 끝이 줄바꿈 문자로 끝나면 세미콜론을 생략할 수 있다
var bValue = true var sValue = "This is also true";
- 만약 한 줄에 여러개의 구문을 넣고자 한다면 반드시 각 구문의 끝에 세미콜론을 붙여야 한다
var bValue = true; var sValue = "This is also true"
- 각 구문의 끝에 세미콜론을 항상 붙이는 것이 좋다
다음과 같이 굳이 필요치 않은 곳에 공백 문자(탭 / 스페이스 / 줄바꿈)가 잘못 들어가더라도 코드의 동작에는 문제가 없다
var firstName = 'Shelley'; var alert(firstName);
줄바꿈 문자를 구문 종료자로 해셕
var firstName var lastName = 'Powers';
위의 경우 에러 발생
- 첫 번째 줄에서 한 구문이 완성되지 않았기 때문에 다움 줄의 내용을 그 구문의 연장으로 보는데,
- 두 번쨰 줄의 내용은 배정문의 연장 내용으로 적합하지 않다
단순 구문
배정문
- 가장 많이 사용하는 구문
- 형식
- 배정연산자(=)
- 왼쪽에는 변수명,
- 오른쪽에는 배정값
- 배정할 값은 상수 값
- nValue = 25.00;
- 변수 및 상수를 연산자를 조합해 사용
- nValue = nValue + 25.00;
- 함수 호출문
- nValue = someFuncton();
- 한 줄에 하나 이상의 배정문을 사용
- 아래는 한 줄에서 빈 문자열("")을 여러 개의 변수에 배정하는 예
- var firstName = lastName = middleName = "";
- 아래는 한 줄에서 빈 문자열("")을 여러 개의 변수에 배정하는 예
var sValue = "A"; var sValue = "B"; var sValue = "C"; var sValue = "D"; alert(sValue);
- 배정연산자(=)
산술 구문
- nValue = nValue + 25.00;
- 상수, 변수, 산출 연산자를 여러 개 사용하여 더 복잡한 구문을 표현
- nValue = nValue + 20.00 / 2 - nValue2 * 3;
이항 연산자
- 피연산자가 두 개(연산자의 양쪽에 각각 하나씩)
- 덧셈 +
- 뺄셈 -
- 곱셈 *
- 나눗셈 /
- 나머지 %
- 여러 가지 타입의 숫자를 사용할 수 있으며, 결과값은 하나의 변수에 저장
- var nValue = varA * 6.0 + 3.45 - varB / 0.05;
- 숫자 대신 문자열을 사용하면
- var newString = "This is on old " + oldString;
- 덧셈 기호( + )를 숫자에 사용하면 덧셈 연산자
- 문자열에 사용하면 연결 연산자
- 다른 이항 연산자에서도 문자열을 피연산자로 사용할 수 있음
- 이때 문자열은 숫자로 구성되어야 하며
- 해당 문자열은 숫자로 변환되어 계산
- var newValue = 3.5 * 2.0; // 결과값은 7 이다
- var newValue = 3.5 * "2.0"; // 결과값은 7 이다
- var newValue = "3.5" * "2.0"; // 결과값은 7 이다
- 숫자 상수와 변수 문자열을 더하려고 할 때는
- 숫자가 문자열로 변환되어 계산
- 이 차이점을 명확히 구분해서 알아야 함
- var newValue = 3.5 + "2.0"; // 결과값은 "3.52.0"
단항 연산자
- 3 가지
- 값증가 ++
- 값감소 --
- 음수값 표현
someValue = 34; var iValue = -someValue; iValue++; document.writeln(iValue);
- iValue = iValue + 1;
- 최종값은 -33;
- 증감연산자
- 연산자가
- 변수 앞에 위치하는 경우에는 값이 먼저 증가/감소 된 후 해당 구문이 수행
- 변수 뒤에 위치하는 경우에는 현재 값을 가지고 구문이 수행되고 나서 값이 증가/감소
var iValue = 3; var iValue2 = ++iValue; // iValue 값이 4가 된 다음, iValue2값이 4가 된다 var iValue3 = iValue++; // iValue3 값이 4가 된 다음, iValue값이 5가 된다 var iValue4 = iValue; // iValue4 값이 5가 되고, iValue 값은 그대로다.
- 연산자가
연산자의 우선순위
- 사용된 연산자가 모두 동일한 우선순위를 가질때
- 왼쪽에서 오른쪽의 순서로 수행
- 우선순위가 다른 경우엔
- 우선순위가 가장 높은것부터 차례대로 수행
nValue = 3, nValue2 = 6
복합 배정 연산자
- 배정 연산과 산술 연산을 하나의 구문으로 간단하게 함칠 수 있음
모든 이항 산술 연산자는 위와 같은 간편한 형식을 사용할 수 있다
연산자 설명 += 기존 변수의 값에 값을 더합니다 -= 기존 변수의 값에 값을 뺍니다 *= 기존 변수의 값에 값을 곱합니다 /= 기존 변수의 값에 값을 나눕니다 %= 기존 변수의 값에 나머지를 구합니다 nValue %= 3;
- nValue -= 3;
- nValue *= 4;
- nValue += 5;
아래 나오는 네가지의 비트 연산자에도 이를 적용할 수 있음
비트 연산자
- 비트 연산자는 피연산자를 0과 1로 구성된 32비트 값으로 간주
- 비트를 조작하여 결과를 생성
- 조작 방법
- 연산자의 종류에 따라 아래와 같다
- &
- 비트 AND 연산 : 두 비트 모두 1일 때만 결과 비트가 1
- |
- 비트 OR 연산 : 두 비트 중 하나 또는 둘 다 1일 때 결과 비트가 1
- ^
- 비트 XOR 연산 : 두 비트가 서로 다를 때 결과 비트가 1이 되고 서로 같을 때는 0이 된다
- ~
- 비트 NOT 연산 : 입력 비트의 보수 값을 반환한다(0이면 1, 1이면 0)
- &
var flags = 0x5; // 이진수 0101 // flag_A: false // flag_B: true // flag_C: false // flag_D: true var flag_A = 0x1; // 0001 var flag_B = 0x2; // 0010 var flag_C = 0x4; // 0100 var flag_D = 0x8; // 1000 // flags 변수가 flag_C에 설정되어 있는지 알아내기 위해서는 논리곱 연산자(&)를 사용한다 if (flags & flag_C) { something do }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Using Binary Flags</title> <script> var FIELD_A = 0X1; // 00001 var FIELD_B = 0X2; // 00010 var FIELD_C = 0X4; // 00100 var FIELD_D = 0X8; // 01000 var FIELD_E = 0X10; // 10000 // 필드 A, C, E 값이 채워져 있다(1로 설정됨) 고 가정 var fieldsSet = FIELD_A | FIELD_C | FIELD_E; // 00001 | 00100 | 10000 => 10101 if ((fieldsSet & FIELD_A) && (fieldsSet & FIELD_C)) { alert("Fields A and C are set"); } </script> </head> <body> <p> Imagine a form with five fields and a button here.. </p> </body> </html>
- 연산자의 종류에 따라 아래와 같다
세 가지의 비트 연산자
- <<
- >>
- 각각 왼쪽 피연산자의 비트들을 지정한 값(0에서 31 사이의 값)만큼 왼쪽 또는 오른쪽으로 이동
- >>>
- 오른쪽으로 이동하되, 그에 따라 값이 비워지는 부분을 0으로 채운다
- newValue = oldValue >>> 3;
프로그램의 흐름과 조건문
- 프로그램 흐름은 일반적으로 순차적
- 실행 순서를 바꾸기 위해서는 특별한 코드를 추가
- 특정한 이벤트가 발생했으 때에만 함수를 호출
- 조건 검사를 수행해서 결과가 참을 때만 특정 코드가 실행되도록 할 수 있다
- 프로그램의 흐름을 바꾸는 데에 조건문을 사용
- 조건문의 형식
if (value) { statements processed; }
'조건' 이라는 용어는 특정 조건이 만족되어야만 코드가 실행된다는 의미에서 붙여진 이름
- 위의 예는 소괄호 안의 값(수식의 결과 /변수 / 상수)이 참으로 평가되면 블록 안의 코드를 실행
- 그렇지 않으면 블록을 건너뛰어 그 다음부터 실행
- 조건 실행 구문이 하나라도 하더라도 중괄호로 감싸주는 습관을 들이는게 좋다
- 코드가 복잡한 경우(길거나 중첩이 많은 경우)에는 중괄호를 닫을 때
- 간단한 주석을 달아주면 가독성이 높아짐
- 유지보수 하기가 쉬워짐
if ... else 조건문
- 조건 검사의 결과가 거짓일 때 시행할 구문들을 else 의 중괄호 블럭에 넣는다
if (expression) { ... } else { ... } // stateCode 값이 MA(Massachusetts)면 // 세금이 3.5 // 아니면 4.5 if (stateCode == "MA") { taxPercentage = 3.5; } else { texPercentage = 4.5; }
여러 개 중에서 하나를 선택하기 위해 여러가지 조건을 검사해야 할 때
- else 구문 뒤에 또 다른 조건 검사 구문(if ... else 등)을 넣어서 사용
if (조건문) { 코드블럭... } else if (또다른조건문) { 코드블럭... } // // var stateCode = 'MO'; if (stateCode == 'OR') { taxPercentage = 3.5; } else if (stateCode == 'CA') { taxPercentage = 5.0; } else if (stateCode == 'MO') { taxPercentage = 1.0; } else { taxPercentage = 2.0; } alert(texPercentage);
하나의 변수에 대해 여러 가지 조건을 검사하려면 else if 구문을 여러개 추가
- 하지만 코드의 가독성이 떨어지고 조잡
- 이런 경우 switch 구문 사용
switch 조건문
- switch 구문은 주로 조건식의 결과가 여러 가지일 경우 사용
- 조건식을 평가한 후, 그 결과에 따라서 여러 개의 구문 블럭 중 하나를 선택하여 실행
switch (조건식) { case firstlabel: 실행 구문; [break;] case secondlabel: 실행 구문; [break;] ... case lastlabel: 실행 구문; [break;] default: 실행 구문; }
조건식을 평가한 값을 case 레이블의 값과 비교하여 일치하는 것을 발견할 때까지 위에서부터 아래로 찾아간다
- 일치하는 레이블을 발견하면 그 부분부터 switch 구문이 끝날 때까지 실행을 계속한다
- 단 break문을 만나면 곧바로 switch문의 끝으로 이동
- 일치하는 레이블이 없다면 default문의 코드를 처리하고
- 없으면 아무 일도 수행하지 않고
- switch문의 다음 줄부터 처리를 계속한다
- case 레이블마다 하나의 코드 블럭만 실행하고 싶다면
- 각 case문의 끝에 break문을 넣어줌
- 2개 이상의 case 문에 대해서 동일한 코드를 수행하고자 한다면
case labelone: case labeltwo: case labelthree: statements; break;
위의 세개의 레이블(labelone, labeltwo, labelthree) 중 어느 하나에만 일치하면 해당 구문을 실행
- stateCode 값을 평가하여
- OR, MA, WI이면
- statePercentage를 0.5, taxPercentage를 3.5
- MO
- 1.0 / 1.5
- CA, NY, VT
- 4.5 / 2.6
- TX
- 3.0 / 0.0
- 그 외의 경우는
- 2.0 / 2.3
var statCode = 'NY'; var statePercentage = 0.0; var taxPercentage = 0.0; switch (stateCode) { case 'OR', 'MA', 'WI' : statePercentage = 0.5; taxPercentage = 3.5; break; case 'MO' : statePercentage = 1.0; taxPercentage = 1.5; break; case 'CA' : case 'NY' : case 'VT' : statePercentage = 2.6; taxPercentage = 4.5; break; case 'TX' : taxPercentage = 3.0; break; break : statePercentage = 2.0; taxPercentage = 2.3; break; } alert("tax is " + taxPercentage + " and stat is " + statePercentage);
- OR, MA, WI이면
조건 연산자
- 조건 연산자는 지정된 조건(동등, 식별, 관계, 논리)을 검사하는 데 사용
- 처리 방법이나 복잡한 정도는 다를지라도 그 결과는 참 또는 거짓 중의 하나
동등/일치 연산자
- (==) 동등 연산자
- var nValue = 3;
- if (nValue == 3) ... // ... 부분은 조건과 일치할 때 실행할 코드
- 동등 연산자도 덧셈 연사자와 마찬가지로 수식 평가에서 가급적 에러를 발생시키지 않기 위해 변수의 데이터 타입을 자동으로 변환
- 예
- 한쪽이 숫자
- 다른 쪽이 문자열인 경우
- 의마상 동일한 숫자이면 참을 반환
var nValue = 3.0; var sValue = "3.0"; if (nValue == sValue) ...
switch문 동등연산자가 묵시적으로 사용된 경우에는 다음 두 case문 모두가 일치된다고 판단
case 3.0: ... case "3.0": ...
- 예
(===) 일치 연산자
- 값과 데이터 타입을 비교하는데 사용하며,
- 두 피연산자가 값과 데이터 타입이 모두 동일할 때에만 참을 반환
- if (nValue === sValue) ...
- if (nName !== "Smith") ...
var nValue = 3.0; var sValue = "3.0"; alert (nValue == sValue); // true alert (nValue === sValue); // false
var nValue = 3.0; var sValue = "3.0"; if (nValue == "3.0") alert("According to equality, value is 3.0"); // alert if (nValue === "3.0") alert("According to identity, value is 3.0"); if (sValue != 3.0) alert("According to equality, value is not 3.0"); if (sValue !== 3.0) alert("According to identity, value is not 3.0"); // alert
기타 관계 연산자들
- 관계 연산자는 하나의 피연산자와 다른 피연산자를 비교한 결과에 따라 코드를 실행
- 동등 / 일치 연산자는 동일 여부를 비교한느 관계 연산자
- boolean 데이터 타입 참고
삼항 조건 연산자
- 조건 연산자
- 하나뿐
- (조건식) ? 참일때 값 : 거짓일 때 값;
var nValue = 1.0; var sResult = (nValue > 0.5) ? "value over 0.5" : "value not over 0.5";
if ... else 변경시
var stateCode = 'OR'; var taxPercentage = 0.0; if (stateCode == 'OR') { tzxPercentage = 3.5; } else { taxPercentage = 4.5; } // 위의 코드를 삼항 연산자로 바꾸면 var taxPercentage = (stateCode == 'OR') ? 3.5 : 4.5;
이해하기 쉽고 사용이 간편하기 때문에 자주 이용
- 브라우저의 차이점을 해결하는 데도 사용
논리 연산자
- 세가지
- 두 가지는 이항 연산자
- 한 가지는 단항 연산자
연산자 설명 ! 논리 부정 연산자 && 논리곱 연산자 || 논리합 연산자 논리 AND(&&) 및 OR(||) 연산자의 경우에는 단축 평가(short-circuit evaluation)를 먼저 적용
- 논리곱(AND) 의 경우
- 왼쪽 조건식이 거짓으로 판명되면
- 전체 조건식이 무조건 거짓이 되므로
- 오른쪽 조건식을 검사하지 않는다
- 왼쪽 조건식이 거짓으로 판명되면
- 논리합(OR) 의 경우
- 왼쪽 수식이 참일 경우
- 전체 조건식이 무조건 참이 되므로
- 오른쪽 조건식을 검사하지 않는다
- 왼쪽 수식이 참일 경우
- 단축 평가를 이해했다면
- 왼쪽 조건식에 자원(CPU등)을 적게 사용하는 코드를 위치시킴으로써
- 전체 프로그램의 효율을 높밀 수 있다
- 논리곱(AND) 의 경우
반복문
- 반복문에는 if ... else ... 문과 마찬가지로 조건 검사 부분이 포함
- if 와 반복문 차이점
- 조건식이 참으로 판단되면
- 코드 블럭을 수행하고 난 다음, 다시 조건식으로 돌아와 검사를 반복
- 조건식이 참으로 판단되면
while 반복문
- 시작 부분에서 조건식을 검사해 참일 때, 루프를 반복
- 조건식의 결과가 거짓이면 반복을 종료
var iValue = 0; while (iValue < 10) { iValue++; document.writeln("iValue is " + iValue + "<br />"); }
조건식을 검사한 후, 코드 블록을 반복적으로 실행
- 처음 조건식을 검사했을 때 거짓이 되면 코드는 한 번도 실행되지 않음
do ... while 반복문
- 조건식의 참/거짓 여부와 상관 없이 코드 블럭을 최소한 한 번은 실행 할 때 사용
- do ... while 문은 조건식이 맨 마지막에 위치하기 때문에 코드 블럭을 먼저 수행한 다음 조건식을 검사
- 최소한 한 번의 실행을 보장
do { iValue++; document.writeln("iValue is " + iValue + "<br />"); } while (iValue < 10)
조건식은 다음과 같이 복잡할 수도 있다
- while (iValue <10 && iValue >= 3)
for 문
- 일반적인 조건을 사용하지 않고 정행진 횟수만큼 반복시키고자 할 때 사용
- 두가지 종료
- 세단계로 구성
- for (초기값; 조건검사; 업데이트) { }
- 변수의 초기값을 설정하는 단계
- 반복될 때마다 변수값을 업데이트하는 단계
- 변수값이 특정 조건을 만족하여 반복이 종료되는 단계
for (var i = 0; i < 10; i++) { document.writeln("hellow<br />"); }
- 세단계로 구성
for in 반복문
- 배열의 각 요소를 차례대로 접근하는 방식
- for (객체 내의 변수들) { }
- for (var i in array) { }
for (var i in array) { } // 위의 for in 반복문과 같은 단순 반복문 for (var i = 0; i < array.length; i++) { } // 예 // 배열을 선언합니다. var array = ['아메리키노', '카페라떼', '초코', '밀크']; // 반복문 for (var i in array) { alert(array[i]); }
/ Callback function (콜백함수) callback_function
// 컬러 범위 체크 콜백 함수 function checkColor(element, index, array) { return (element >= 0 && element < 256); } // RGB 세개의 값을 모두 갖고 있는지 확인 function checkCount(element, index, array) { return (element.length == 3); } // 컬러 배열 var colors = new Array(); colors[0] = [ 0,262,255]; colors[1] = [255,255,255]; colors[2] = [255, 0, 0]; colors[3] = [ 0,255, 0]; colors[4] = [ 0, 0,255]; colors[5] = [ -5,999,255]; // 컬러 범위를 필터링한다 var testedColors = new Array(); for (var i in colors) { testedColors[i] = colors[i].filter(checkColor); } // 세 값에 대한 필터링 var newTested = testedColors.filter(checkCount); for (i in newTested) { document.writeln(newTested[i] + "<br />"); }
중첩 반복문
- 반복문을 여러 겹 중첩해 사용하면 중첩 반복문
// * // ** // *** // **** // ***** // 변수를 선언합니다. var output = ""; // 반복문 for (var i = 0; i < 6; i++) { for (var j = 0; j < i; j++) { output += '*'; } output += '\n'; } // 출력 alert(output);
break 키워드
- switch 조건문에서 사용
- switch 조건문이나 반복문을 벗어날 때 사용
// 아래의 로프는 무한 루프 while (true) { ... } // 위와 같은 무한루프는 break 키워드를 사용해야 벗어날 수 있음 while (true) { if (조건식) { break; } } // 반복문 for (var i = 0; true; i++) { alert(i + "번째 반복문입니다."); // 진행여부를 물어봅니다 if (!confirm("계속하시겠습니까?")) { break; } } alert("프로그램 종료");
continue 키워드
- 반복문 내에서 현재 반복을 멈추고
- 다음 반복을 진행시키는 키워드
// 반복문 for (var i = 0; i < 5; i++) { // 현재 반복을 중지하고 다음 반복을 수행 continue; alert(i); }
alert() 함수를 실행하지 않음
- continue 를 사용한 1~ 10까지 짝수 합 구하기
// 변수를 선언 var total = 0; // 반복문 for(var i = 1; i <= 10; i++) { // 조건문 if (i % 2 == 1) { // 홀수면 현재 반복을 중지하고 다음 반복을 수행 continue; } total += i; } alert(total);
함수
- 실제로는 객체
- 함수는 정의 / 생성 할 수 있으며, 심지어 출력할 수도 있다
- 객체의 특성 덕분에 함수를 변수나 배열에 배정할 수 있다
- 다른 함수를 호출할 때 인자로 넘겨 줄 수도 있다
- 함수 사용이 편리하고 유연
- 혼란스럽기도 함
- 익명함수
- 함수 구문, 함수 표현, 리터럴 함수 참조보다 이해하기가 매우 까다로움
- 함수에서 상속된 프로퍼티, 함수 클로저와 메모리 누수도 까다로움
함수 개요
- 함수 생성하는 세가지 방법
- 선언적 함수
- function 키워드로 시작하는 함수
- 한 번만 파싱
- 정적
- 함수명을 지정
- 익명 함수
- 생성자를 이용해서 생성한 함수
- 접근할 때마다 파싱
- 함수명을 지정하지 않음
- 함수 리터럴
- 다른 구문 내에서 식의 한 부분으로 생성된 함수
- 한 번만 파싱
- 정적
- 함수명은 지정할 수도 있고
- 함수명은 지정하지 않을 수도 있다
- 함수명을 지정한 경우엔 그 함수 내에서만 접근이 가능
- 콜백 함수가 필요한 객체 이벤트 핸들러와 함께 사용
- 선언적 함수
- var 함수 = function () { }
var 함수 = function() { var output = prompt('숫자를 넣으세요', '숫자'); alert(output); }; alert(함수);
위는 익명함수
참조 reference
- 객체의 실제 위치를 가르키는 포인터
- 서로 다른 변수 들이 동일한 객체를 가리킬 수 있다
// 동일한 객체를 가리키는 여러 변수들에 대한 예 var obj = new Object(); var objRef = obj; obj.oneProperty = true; alert(obj.oneProperty == objRef.oneProperty); // 스스로를 수정할 수 있는 객체 var items = new Array("one", "two"); var itemsRef = items; // 원본에 아이템 추가 items.push("three"); alert(items.length == itemsRef.length); // 원래 객체는 그대로두고 한 객체의 참조를 변경 var items = new Array("one", "two"); var itemsRef = items; // 새로운 객체 추가 items = new Array("가나", "다라마"); alert(items != itemsRef); // 내용을 수정할 수 없는 새로운 객체를 만드는 객체 수정에 대한 예 var item = "test"; var itemRef = item; item += "ing"; alert(item != itemRef);
함수 리터럴
- 함수식 - 식의 일부분으로 함수가 생성되기 때문
- 함수를 생성해 변수에 할당하기 위해 생성자를 사용할 필요가 없음
var func = function(매개 변수들) { 구문; };
매개변수
- 함수를 호출하는 쪽과 호출된 함수를 연결하는 매개가 되는 변수
- 자바스크립트는 함수를 생성할 때 지정한 매개 변수보다 많거나 적은 매개 변수를 사용하는 것을 허용
- 많게 입력
- 추가된 매개 변수는 무시
- 적게 입력
- 미지정 매개 변수에 undefined가 입력
alert('원래 매개 변수입니다', '추가된 매개 변수 입니다'); prompt('원래 매개 변수입니다.');
매개 변수 보다 많거나 적게 매게 변수를 사용하는 점을 이용
// 배열 생성 var array1 = Array(); var array2 = Array(10); var array3 = Array(123, 45, 6, 78, 9, 1011); // 배열을 사용 alert(array1 + '\n' + array2 + '\n' + array3 + '\n');
Array()함수의 매개 변수에 따른 차이
함수 형태 설명 Array() 빈 배열을 만듬 Array(number) 매개 변수만큼의 크기를 가지는 배열을 만듬 Array(mixed, ..., mixed) 매개 변수를 배열로 만듬
this 키워드/콘텍스트context
- 자바스크립트에서 작성하는 코드는 어떤 형태로든 항상 콘텍스트(그 속에서 코드가 돌아가는 객체)에 속하게 된다
- 콘텍스트는 this 변수를 통해 작동
- this 변수는 항상 코드가 속한 객체를 가리킴
- 전역 변수들이 실제로는 window 객체의 프로퍼티
- 전역 콘텍스트에서도 this 변수가 어떤 객체를 가리킴
- this 키워드는 편리함을 위해 사용
// 한 콘텍스트 안에서 함수를 사용한 후 콘텍스트를 다른 변수로 바꾸는 예 var obj = { yes : function() { // this == obj this.val = true; }, no : function() { this.val = false; } }; //----------------------- // 'obj'객체에 val 프로퍼티 없다 alert(obj.val == null); // yes 함수를 호출하면 'obj'객체와 연결된 // val 프로퍼티의 값이 바뀐다 obj.yes(); alert(obj.val == true); // 이제 window.no가 메서드 obj.no를 가리키게 한 다음 메서드를 실행 window.no = obj.no; window.no(); // obj 객체는 그대로 있고 // 콘텍스트가 window 객체로 바뀌었기 때문에 alert(obj.val == true); // window의 val 프로퍼티 값이 바뀌었다 alert(window.val == false);
콘텍스트를 바꾸는 메서드
- call
- 호출할 함수에 전달할 메개변수를 별개의 인자들로 받음
- apply
- 호출할 함수에 전달할 매개변수를 배열로 받음
- bind
- this값을 고정시키거나
- 특정 객체에 바인딩 되도록 처음부터 정해 놓을때 사용
- call
// 함수 콘텍스트를 바꾸는 예 // 자신의 콘텍스트 색을 변경하는 간단한 함수 function changeColor(color) { this.style.color = color; } // window 객체에는 stlye 객체가 존재하지 않으므로 // window 객체에 대고 호출하면 호출이 실패 changeColor("white"); // ID가 main 인 엘리먼트를 찾는다 var main = document.getElementById("main"); // call 메서드를 사용해 검은색으로 바꾼다 // call 메서드를 첫 번째 전달인자를 콘텍스트로 설정하고 // 나머지 전달인자를 함수의 전달인자로 넘긴다 changeColor.call(main, "black"); // body 엘리먼트의 색을 설정하는 함수 function setBodyColor() { // apply 메서드는 첫 번째 전달인자인 body엘리먼트로 // 콘텍스트를 설정한다. 전달인자 배열인 두 번쨰 전달인자는 // 함수의 전달인자로 넘긴다 changeColor.apply(document.body, arguments); } // body 엘리먼트의 배경색을 검은색으로 설정한다 setBodyColor("black"); //------------------------- //------------------------- var one = { name: "object", say : function(greet) { return greet + ", " + this.name; } }; //테스트 one.say('hi'); // "hi, object" // 또 다른 객체는 two는 say() 메서드를 가지고 있지 않지만 one 의 메서드를 사용할 수 있다 var two = { name:"another object" }; one.say.apply(two, ['hello']); // "hello, another object" // say() 내부의 this가 two를 가리키고 있기 때문에 this.name 은 "another object"가 된다 // 이 함수 포인터가 전역변수를 가리키게 될 경우 // 이 함수를 콜백 함수로 전달하는 경우에는 ? // 함수를 변수에 할당하면 함수 안의 this는 전역 객체를 가리킴 var say = one.say; say('hoho'); // "hoho, undefined" // 콜백함수로 전달한 경우 var yetanother = { name: "Yet another object", method: function(callback) { return callback('Hola'); } }; yetanother.method(one.say); // "Hola, undefined" // 두가지 모두 say()안의 this가 전역객체를 가리키기때문에 코드가 제대로 동작 안됨 function bind(o, m) { return function() { return m.apply(o, [].slice.call(arguments)); } } // 이 바인드 함수는 o라는 객체와 m이라는 메서드를 인자로 받아 // 이 둘을 바인딩한 새로운 함수를 반환 // var twosay = bind(two, one.say); twosay('yo'); // "yo, another object" // twosay() 전역 함수로 생성되었지만 this가 전역 객체를 가리키지 않고 // bind()에 전달된 two객체를 가리킴 // ECMAScript 에서 제공하는 bind사용 var twosay2 = one.say.bind(two); twosay2('yo'); "yo, another object"
익명함수
- 직접적으로 선언하거나 명명한 적이 없기 때문
- 함수 또한 객체
- 객체는 런타임에 동적으로 생성할 수 있다
var sayHi = new Function("toWhom", "alert('Hi ' + toWhom);"); sayHi("World!");
생성자를 사용하여 익명함수를 정의하는 방법
- var variable = new Function("인자1", "인자2", "인자3", ... "인자n", "함수몸체");
- var func = new Function("x", "y", "return x * y");
- 선언적 /정적 함수
- function func(x, y) {
- return x * y;
- }
// 대화상자를 띄워 함수 몸체와 인자 값을 입력받는다 // return x * y var func = prompt("Enter function body:"); var x = prompt("Enter value of x:"); var y = prompt("Enter value of y:"); // 결과를 호출한다 var op = new Function("x", "y", func); var theAnswer = op(x, y); // 결과를 출력한다 document.writeln("Function is: " + func + "<br />"); document.writeln("x is x: " + x + " y is y: " + y + "<br />"); document.writeln("The answer is: " + theAnswer);
선언적 함수
- function 함수명(인자1, 인자2, ..., 인자n) {
- 함수의 실행 구문이 위치하는 곳;
- }
- var 함수 = function() { };
- 함수();
- 선언적 함수도 익명적 함수와 마찬가지 방법으로 만들고 사용
function() { } var 함수 = function() { }; function sayHI(toWhom) { alert("Hi " + toWhom); } sayHi("World!");
선언적 함수의 재정의
// 1 function 함수() { alert('함수 A'); } function 함수() { alert('함수 B'); } 함수(); // 2 var 함수 = function() { alert('함수 A'); } var 함수 = function() { alert('함수 B'); } 함수(); // 3 // 오류 함수(); var 함수 = function() { alert('함수 A'); } var 함수 = function() { alert('함수 B'); } // 4 // 오류 발생 안함 함수(); function 함수() { alert('함수 A'); } function 함수() { alert('함수 B'); }
내부 함수
- 함수 내부에 선언한 함수
function outer(args) { function inner (args) { inner statements; } }
대규모의 웹 애플리케이션 작성시, 같은 이름으로 함수 생길 경우 문제
- 내부 함수를 이용해 해결
// 제곱을 구하는 함수 function square(x) { return x * x; } // 피타고라스 함수 function pythagoras(width, height) { return Math.sqrt(square(width) + square(height)); } // 함수 충돌 // A가 만든 함수 // 제곱을 구하는 함수 // 제곱을 구하는 함수 function square(x) { return x * x; } // 피타고라스 함수 function pythagoras(width, height) { return Math.sqrt(square(width) + square(height)); } alert(pythagoras(3,4)); // B가 만든 함수 // 삼각형이 직각인지 확인하는 함수 function square(width, height, hypotenuse) { if (width * width + height * height == hypotenuse * hypotenuse) { return true; } else { return false; } } // -------------------------- // // 내부 함수 작성 // 피타고라스 함수 function pythagoras(width, height) { function square(x) { return x * x; } return Math.sqrt(square(width) + square(height)); }
함수를 매개 변수로 받는 함수
- 함수도 하나의 자료형이므로 쉽게 매개 변수로 전달
익명함수 전달
// 함수 5번 호출 function callFunctionFiveTimes(otherFunction) { for (var i = 0; i < 5; i++) { otherFunction(); } } // callFunctionTenTimes() 함수 호출 callFunctionFiveTimes(function () { alert('Hello World..!'); });
선언적 함수 전달
// 함수 10번 호출 function callFunctionFiveTimes(otherFunction) { for (var i = 0; i < 5; i++) { otherFunction(); } } // justFunction()함수 function justFunction() { alert('Hello World..!'); } // callFunctionTenTimes() 함수 호출 callFunctionFiveTimes(justFunction);
함수를 리턴하는 함수와 클로저
- 함수를 리턴하는 함수
익명 함수를 리턴하는 함수
function outerFunction() { return function() { alert('Hello Wolrd!'); }; } ourterFunction();
지역 변수의 유효 범위
// 함수 선언 function test(name) { var output = 'Hello ' + name + ' ..!'; } // alert(output);
오류 발생
- output 은 지역 변수이므로 함수 외부에서 사용할 수 없슴
- 지역 변수는 함수가 실행될 때 생성되고
- 함수가 종료될 때 사라짐
- 하지만
- 클로저를 사용하면
- 이 규칙은 위반할 수 있슴
- 아래 코드에서 지역 변수 output은 함수 outerFunction을 실행할 때 생성
- 자바스크립트 스스로 아직 지역 변수 output을 지우면 안 된다는 것을 인식하고
- 남겨두므로 발생하는 특성
// 함수 선언 function outerFunction(name) { var output = 'Hello ' + name + ' ..!'; return function() { alert(output); }; } // var o = outerFunction("slipp"); o();
다양한 클로저 정의
위의 예저에서
지역 변수를 남겨두는 현상을 클로저
- 함수 outerFunction() 내부의 변수들이 살아있는 것이므로 함수 outerFunction()으로 인해 생성된 공간을 클로저
- 리턴되는 함수 자체를 클로저
- 살아남은 지역 변수 output을 클로저
- 지역 변수 output을 남겨둔다고 외부에서 마음대로 사용할 수 있는 것은 아님
- 반드시 리턴된 클로져 함수를 사용해서만 지역 변수 output을 사용
- 클로저 함수로 인해 남는 지역 변수는 각각의 클로저의 고유한 변수
// 함수 선언 function outerFunction(name) { var output = 'Hello ' + name + ' !'; return function() { alert(output); }; } // 변수 선언 var first = outerFunction('Slipp'); var second = outerFunction('X-Man'); // 실행 first(); second(); // 고유한 지역 변수 output을 가지고 있음
고유한 지역 변수를 가지고 있음
- 위의 코드 참고
- 클로저를 사용하면
- 클로저를 사용하는 여러 함수를 생성하는데 필요한 유효범위를 만드는 익명 함수의 예
무엇이 잘못인지 설명
// 객체 생성 var obj = Object(); function oAction(obj) { // 객체에 연결할 아이템 배열 var items = ['click', 'keypress']; // 각 아이템을 처리한다 for (var i = 0; i < items.length; i++) { // 유효범위를 만들기 위해 스스로를 실행하는 익명 함수를 사용 (function(){ // 함수를 객체에 연결 obj['on'+items[i]] = function() { // 다음에 나오는 변수 items[i]는 유효범위가 for 루프인 // 부모 변수 items[i]를 참조한다 alert('Thanks for your ' + items[i]); }; })(); } }
재귀 함수 Recursion
- 자신을 다시 호출하는 함수
- 프로세스가 두 번이상 수행되어야 할 때 사용
- 앞서 실행된 결과에 새로운 반복 처리가 계속적으로 실행
- 트리 구조 내의 데이터를 다루는 경우에는 유용
- DOM 이 대표적
- 복잡하고, 구현/유지보수가 어려움
- 메모리 및 자원을 낭비할 수 있다
function factorial(num) { var result = 1; for (var i = num; i > 0; i--) { result *= i; } return result; } // Recursion function factorial(num) { if (1 === num) { return num; } else { return num * factorial(num - 1); } }
자기-호출 함수 Self-invoke Function
- 함수를 정의한 직후에 바로 실행하는 함수
- 단순히 괄호안에 익명함수를 정의하고 다른 괄호로 바로 실행
- 익명함수가 처리 할 수 있는 매개 변수 가능
- 장점
- 몇가지 작업을 전역변수를 생성하지 않고 실행 가능
- 단점
- 루프 또는 다른 함수에 넣지 않는한, 두번 같은 기능을 실행 할 수 없다
- 사용
- 일회성이나 초기화 작업에 대한 익명의 자기-호출 함수가 가장 적함
// //-------------------------------- // // Self-invoking Functions // ( function(){ alert('boo'); } )() ( function(name){ alert('안녕 ' + name + '!'); } )('슬립')
콜백 함수
- 스레드를 사용하는 대신 프로그램적인 대안으로 자바스크립트에서는 비동기식 콜백을 사용
- 원하는 시점에 실행될 코드에 대한 참조를 제공하면 됨
- 브라우저가 나머지 작업을 진행
- 이벤트 핸들러와 콜백을 사용하는 예
// 자바스크립트 비동기식 콜백 // 페이지가 로딩될 때마다 호출할 함수를 등록 window.onload = loaded; // 페이지가 로딩될 때마다 호출할 함수 function loaded() { // 페이지가 로딩되었으니, 필요한 작업을 시작한다 alert("페이지 로딩 완료"); }
이벤트와 연계된 부분은 JavaScript기본-이벤트 event 파트를 참고할 것
- 메소드 실행 시에 자동으로 호출되는 함수
- filter
- 특정 조선을 만족하지 못하는 원소가 추가 되지 않도록 처리
- 직접 값을 테스트해서 배열에 추가하는 대신, 배열에 넘겨주기만 하면 filter 가 알아서 처리
- forEach
- 함수로 인자 필요
- 이 함수가 각 원소를 처리
- 함수는 원래의 배열을 변경하지 않음
- every
- 배열의 모든 원소에 대해 false 값이 반환될 때까지 콜백 함수 실행
- map
- 배열의 모든 원소에 대해 콜백 함수 실행
- 그 결과를 새 배열로 생성
- some
- every메소드와 반대로 동작
- 배열릐 모든 원소에 대해 true값이 반환될 때까지 콜백 함수를 실행
- 등
- 이때 사용되는 함수는 함수 리터럴로 일반적으로 콜백 함수라고 함
- Array 객체 참고
- 타이머메서드 참고
- filter
function invoke_and_add(a, b) { return a() + b(); } function one() { return 1; } function two() { return 2; } // callback function one, two invoke_and_add(one, two); // //---------------------------- // function multiplyByTwo(a, b, c) { var i, ar = []; for (i = 0; i < 3; i++) { ar[i] = arguments[i] * 2; } return ar; } function addOne(a) { return a + 1; } multiplyByTwo(1, 2, 3); // [2, 4, 6] addOne(1000); // 1001 var myapp = []; myapp = multiplyByTwo(100, 200, 300); for (var i = 0; i < 3; i++) { myapp[i] = addOne(myapp[i]); } myarr; // [201, 401, 601] function multiplyByTwo(a, b, c, callback) { var i, ar = []; for (i = 0; i < 3; i++) { ar[i] = callback(arguments[i] * 2); } return ar; } myarr = multiplyByTwo(1, 2, 3, addOne); myarr; // [3, 5, 7] myarr = multiplyByTwo(1, 2, 3, function(a){return a + 2;}); myarr; // [4, 6, 8]
자바스크립트 내장함수
인코딩, 디코딩 함수
- 인코딩, 디코딩 관련 내장 함수
함수 이름 설명 escape() 적절한 정도로 인코딩합니다 unescape() 적절한 정도로 디코딩합니다 encodeURI(url) 최소한의 문자만 인코딩합니다 decodeURI(encodedURI) 최소한의 문자만 디코딩합니다 encodeURIComponent(uriComponent) 대부분의 문자를 인코딩합니다 decodeURIComponent(encodedURI) 대부분의 문자를 디코딩합니다 - escape() / unescape()
- ASCII문자열을 URL인코딩 문자열(ISO Latin-1 [ISO 8859-1]) 바꾸어 주는 함수
- HTML로 흔히 사용되는 것으로, 웹프로그램에 데이터를 처리하는 경우에 사용
- 영문 알파벳, 숫자, 일부 특수 문자(@, *, -, _, +, ., /)를 제외한 모든 문자열를 인코딩
- 1바이트 문자는 %XX의 형태
- 2바이트 문자는 %uXXXX의 형태로 변환
- encodeURI() / decodeURI()
- ASCII외의 문자도 인코딩/디코딩 가능
- escape() 함수에서 인터넷 주소에 사용되는 일부 특수 문자(:, ;, /, =, ?, &)는 변환하지 않음
분류 문자 예약 문자 : , / ? : @ & = + $ 인코딩하지 않는 문자 알파벳 십진수숫자 - _ . ! ~ * ' ( ) 스코어 #
- encodeURIComponent() / decodeURIComponent()
- encodeURI에 사용되는 문자 인코딩하고 추가적으로 &, +, = 기호를 인코딩
- AJAX 연산에서 사용
- 알파벳과 숫자를 제외한 모든 문자를 인코딩
- UTF-8 인코딩과 같음
// 인코딩할 URI 만듬 var URI = 'http://www.slipp.net/wiki/pages/viewpage.action?pageId=19530247#JavaScript기본-자바스크립트'; // 출력할 문자열 만듬 var result = ''; result += '--- escape()\n'; result += escape(URI) + '\n\n'; result += '--- encodeURI()\n'; result += encodeURI(URI) + '\n\n'; result += '--- encodeURIComponent()\n'; result += encodeURIComponent(URI) + '\n\n'; // 출력 alert(result);
그외 내장 함수
- 자바스크립트 기본 내장 함수
함수 이름 설명 eval(string) string을 자바스크립트 코드로 실행합니다 isFinite(number) number가 무한한 값인지 확인합니다 isNaN(number) number가 NaN인지 확인합니다 parserInt(string) string을 정수로 바꿉니다 parseFloat(string) string을 실수로 바꿉니다 // eval() // eval() 함수에 사용할 문자열을 만듬 var sEval = ''; sEval += 'var number = 10;'; sEval += 'alert(number);'; // eval() 함수 실행 console.log(sEval); // eval() 함수는 문자열을 자바스크립트 코드로 실행하는 함수 // 함수 eval()을 통해 실행된 코드에서 정의한 변수도 사용할 수 있다 console.log(number); // Infinity, NaN 만들기 var number1 = 10 / 0; // Infinity var number2 = 10 / 'A'; // NaN console.log(number1 + ' / ' + number2); // 내장함수 사용 console.log(isFinite(number1) + ' / ' + isNaN(number2)); // // -Infinity 만들기 var number3 = -10 / 0; // 출력 if (value == Infinity) { console.log('number3 is Infinity'); } else { console.log('number3 is not Infinity'); } // isFinite 함수 사용 if (isFinite(number)) { console.log('number3 is Infinity'); } else { console.log('number3 is not Infinity'); } // NaN은 스스로를 비교할 수 없음 if (NaN == NaN) { console.log('NaN == NaN'); } else { console.log('NaN != NaN'); } // isNaN 함수 사용 if (isNaN(number2)) { console.log('NaN == NaN'); } else { console.log('NaN != NaN'); } // // // Number() 함수 // // var won = Number('10000원'); var dollar = Number('10.01$'); console.log(won + ' / ' + dollar; // var won = '10000원'; var dollar = '10.01$'; console.log(parseInt(won) + ' / ' + parseInt(dollar)); console.log(parseFloat(won) + ' / ' + parseFloat(dollar)); // 진수 변환 parseInt('0x10'); parseInt('273'); parseInt('023'); console.log(parseInt('10', 16)); console.log(parseInt('11', 10)); console.log(parseInt('12', 8)); console.log(parseInt('10', 2)); console.log(parseFloat('12.123e6'));
자바스크립트 객체
개요
- 객체는 크게 4 가지
- 자바스크립트 내장 객체
- 브라우저 객체 모델(BOM Browser Object Model) 객체
- 문서 객체 모델(DOM Document Object Model) 객체
- 개발자가 만든 사용자 정의 객체
- 자바스크립트 객체는 구현 엔진과는 관계없이 언어에 종속되도록 만들어 졌다
- 자바스크립트를 어디에서 구현하느냐와 관계없이(즉, 웹브라우저든 핸드폰이든 무엇이든) 객체를 사용할 수 있다
- 기본 데이터 타입(문자열, 부울, 숫자 등) 유사
- Math, Date, RegExp 특수한 용도의 객체
- RegExp
- 정규표현식의 기능을 제공
- 매우 정교한 문자열 패턴 매칭을 가능하게 함
- RegExp
- 내장 집합 객체인 '배열' Array
- 외형적으로는 그렇게 보이지 않지만 자바스크립트의 모든 객체는 배열을 상속하고 있다
객체 생성자
- Object 객체에 기초
- 자바스크립트를 확장하는 방법은 약간 특이
- 자바스크립트의 현재 버전은 진정으로 객체지향적이라고 할 수 없다
- 생성자의 개념과 new메소드를 사용해 객체 인스턴스 생성을 지원
- 거의 대부분의 내장 객체가 객체 타입과 연관되어 있는 메소드와 프로퍼티를 갖고 있음
- 그 중 일부는 객체 인스턴스를 통해 접근할 수 있다
- 그 외의 것들은 정적
- 즉, 공유 객체를 통해서만 직접적으로 접근이 가능
- Boolean 객체
- 고유 프로퍼티나 메소드를 갖고 있지 않는 유일한 객체는 Boolean 객체
- 이 객체에는 Object 객체 자체의 프로퍼티와 메소드만 존재
// Boolean 객체의 새로운 인스턴스 생성 var bTest = new Boolean(true); // Boolean 객체를 초기화한 후에는, Object의 메소드인 toValue를 사용해서 // 해당 값에 접근 if (bTest.toValue) .... // // OR // 원시 데이터에 접근하는 것처럼 직접 접근할 수 있다 // if (bTest) ...
Number 객체
- Number 객체만의 고유 메소드(문자열로 변환, 특정 로케일의 문자로 변환, 특정 소스점 표현식이나 지수 표현식으로 변환)는 변환과 관련된 것들
- 5 개의 상수 프로퍼티를 갖고 있음
- 이 프로퍼티들은 Number 객체에서 직접 접근 가능
- 스크립트 지원하는 브라우저에 따라 추가적인 상수 프로퍼티가 있음
속성 이름 설명 MAX_VALUE 자바스크립트의 숫자가 나타낼 수 있는 최대 숫자 MIN_VALUE 자바스크립트의 숫자가 나타낼 수 있는 최소 숫자 NEGATIVE_INFINITY 음의 무한대 숫자 POSITIVE_INFINITY 양의 무한대 숫자 NaN 자바스크립트의 숫자로 나타낼 수 없는 숫자 console.log(Number.MAX_VALUE); console.log(Number.MIN_VALUE); console.log(Number.NEGATIVE_INFINITY); console.log(Number.POSITIVE_INFINITY); console.log(Number.NaN); var n = Number.MAX_VALUE; var nInfinity = n + 0.0000000000000001e+308; console.log(n); console.log(nInfinity);
메서드 이름 설명 toExponential() 숫자를 지수 표시로 나타내는 문자열을 만듭니다 toFixed() 숫자를 고정 소수점 표시로 나타낸 문자열을 만듭니다 toPrecision() 숫자를 길이에 따라 지수 표시 또는 고정 소수점 표시로 나타낸 문자열을 만듭니다 toLocaleString() var n = 12.345678901234; console.log(n.toExponential()); console.log(n.toFixed(2)); console.log(n.toFixed(5)); console.log(n.toPrecision(4)); console.log((123.4567890123).toFixed(6)); console.log((1234567890).toLocaleString());
String 객체
- 자바스크립트에서 가장 많이 사용하는 내장 객체
- String 객체 생성 방법 2가지
- var stringFromLiteral = "slipp study";
- var stringFromConstructor = new String("slipp study");
var stringFromLiteral = "slipp study"; var stringFromConstructor = new String("slipp study"); console.log(typeof(stringFromLiteral)); console.log(typeof(stringFromConstructor)); console.log(stringFromLiteral); console.log(stringFromConstructor);
- String 객체의 속성
속성 이름 설명 length 문자열의 길이를 나타냅니다
- Stiring 객체의 메소드
메서드 이름 설명 charAt(position) position에 위치하는 문자를 반환합니다 charCodeAt(position) position에 위치하는 문자이 유니코드를 반환합니다 concat(string, ... , string) 매개 변수로 입력한 문자열을 이어 반환합니다 indexOf(searchString, position) 앞에서부터 일치하는 문자열의 위치를 리턴합니다 lastIndexOf(searchString, position) 뒤에서부터 일치하는 문자열의 위치를 리턴합니다 match(regExp) 문자열 내에 regExp가 있는지 확인합니다 replace(regExp, replacement) regExp를 replacement로 바꾼 뒤 반환합니다 search(regExp) regExp와 일치하는 문자열의 위치를 반환합니다 slice(start, end) 특정 위치의 문자열을 추출해 반환합니다 split(separator, limit) separator로 문자열을 잘라 배열을 반환합니다 substr(start, count) start부터 count만큼 문자열을 잘라서 반환합니다 substring(start, end) start부터 end까지 문자열을 잘라서 반환합니다 toLowerCase() 문자열을 소문자로 바꿔 반환합니다 toUpperCase() 문자열을 대문자로 바꿔 반환합니다 var str = "abcdef"; // str 변환 없음 str.toUpperCase(); console.log(str); // 반환된 값을 받아서 사용 strUpperCase = str.toUpperCase(); console.log(strUpperCase);
String 객체의 HTML 관련 메서드
메서드 이름 설명 anchor() a 태그로 문자열을 감싸 반환합니다 big() big 태그로 문자열을 감싸 반환합니다 blink() blink 태그로 문자열을 감싸 반환합니다 bold() b 태그로 문자열을 감싸 반환합니다 fixed() tt 태그로 문자열을 감싸 반환합니다 fontcolor(colorString) font 태그로 문자열을 감싸고 color속성을 주어 반환합니다 fontsize(fontSize) font 태그로 문자열을 감싸고 size속성을 주어 반환합니다 italics() i 태그로 문자열을 감싸 반환합니다 link(linkRef) a 태그에 href속성을 지정해 반환합니다 small() small 태그로 문자열을 감싸 반환합니다 strike() strike 태그로 문자열을 감싸 반환합니다 sub() sub 태그로 문자열을 감싸 반환합니다 sup() sup 태그로 문자열을 감싸 반환합니다 var str = 'Slipp Study'; var result; result += 'anchor: ' + str.anchor() + '<br />'; result += 'big: ' + str.big() + '<br />'; result += 'blink: ' + str.blink() + '<br />'; result += 'bold: ' + str.bold() + '<br />'; result += 'fixed: ' + str.fixed() + '<br />'; result += 'fontcolor: ' + str.fontcolor('red') + '<br />'; result += 'fontsize: ' + str.fontsize(24) + '<br />'; result += 'italics: ' + str.italics() + '<br />'; result += 'link: ' + str.link('http://www.slipp.net/wiki/pages/viewpage.action?pageId=19530247') + '<br />'; result += 'small: ' + str.small() + '<br />'; result += 'strike: ' + str.strike() + '<br />'; result += 'sub: ' + str.sub() + '<br />'; result += 'sup: ' + str.sup() + '<br />'; document.write(result);
메서드 체이닝
- 자바스크립트의 기술 중 메서드 체이닝(Method Channing)은 메서드를 줄줄이 사용하는 것
var str = 'Slipp Study Team'; str = str.toUpperCase(); str = str.substr(6); str = str.bold(); console.log(str); // method channing str = str.toUpperCase().substr(6).bold();
Array 객체
- Array객체는 여러 가지 자료를 쉽게 관리할 수있게 도와주는 객체
- Array 생성자 함수
생성자 함수 설명 Array() 빈 배열을 만듭니다 Array(number) 매개 변수만큼의 크기를 가지는 배열을 만듭니다 Array(mixed, ... , mixed) 매개 변수를 배열로 만듭니다
- 속성
속성 이름 설명 length 배열 요소의 개수를 알려줍니다
- 관련 메소드
메서드 이름 설명 concat() 매개 변수로 입력한 배열의 요소를 모두 합쳐 배열을 만들어 반환합니다 join() 배열안의 모든 요소를 문자열로 만들어 반환합니다 pop()* 배열의 마지막 요소를 제거하고 반환합니다 push()* 배열의 마지막 부부에 새로운 요소를 추가합니다 reverse()* 배열의 요소 순서를 뒤집습니다 slice() 배열 요소의 지정한 부분을 반환합니다 sort()* 배열의 요소를 정렬하고 반환합니다 splice()* 배열 요소의 지정한 부분을 삭제하고 삭제한 요소를 반환합니다 - *표시된 메서드는 자기 자신을 변화시킵니다
// 변수 선언 var array1 = [1, 2, 3, 4, 5]; var array2 = new Array(); var array3 = new Array(15); var array4 = new Array(6, 7, 8, 9, 10, 11); // var arrayString = ['가', '나', '다라', '마바사', '아자']; var arrayMix = [1, '문자열', function() {}, [9, 8, 7], ['A', 'BC', 'DEF', 'GH', 'I']]; console.log(array1.length); console.log(array2.length); console.log(array3.length); console.log(array4.length); console.log(arrayString.length); console.log(arrayMix.length); console.log(arrayMix[3].length); // // 브라우저 console 에서 실행 // var a = [1, 2, 3]; a; // [1, 2, 3] a[0]; // 1 a[1]; // 2 a.length; // 3 // // 추가 / 수정 Array 요소 // a.[2] = 'three'; a; // [1, 2, "three"] a[3] = 'four'; a; // [1, 2, "three", "four"] var a = [1, 2, 3]; a[6] = 'new'; a; // [1, 2, 3, undefined, undefined, undefined, "new"] // // 삭제 // var a = [1, 2, 3]; delete a[1]; a; // [1, undefined x 1, 3] // // 배열속의 배열 var a = [1, 'two', false, null, undefined]; a; // [1, "two", false, null, undefined] a[5] = [1, 2, 3]; a; // [1, "two", false, null, undefined, Array[3]] var a = [[1,2,3],[4,5,6]]; a; a[0]; // [1, 2, 3] a[0][0]; // 1 a[1][2]; // 6 // // string // var s = 'slipp'; s[0]; // "s" s[1]; // "l" s[2]; // "i" // //--------------------------------- // // var nArray = Array.concat([1,2,3], [4,5]); var fruitArray = ['apple', 'peach', 'orange', 'lemon', 'lime', 'cherry']; fruitArray.sort(); // ["apple", "cherry", "lemon", "lime", "orange", "peach"] var removed = fruitArray.splice(2, 2, 'lemon' ,'banana'); fruitArray; // ["apple", "cherry", "lemon", "banana", "orange", "peach"] removed; // ["lemon", "lime"] fruitArray.join(); // "apple,cherry,lemon,banana,orange,peach" fruitArray.reverse(); // ["peach", "orange", "banana", "lemon", "cherry", "apple"] fruitArray.push('lion'); // ["peach", "orange", "banana", "lemon", "cherry", "apple", "lion"] var sPop = fruitArray.pop(); fruitArray; // ["peach", "orange", "banana", "lemon", "cherry", "apple"] aPop; // "lion" fruitArray.unshift('tiger'); // ["tiger", "peach", "orange", "banana", "lemon", "cherry", "apple"] var sShift = fruitArray.shift(); // ["peach", "orange", "banana", "lemon", "cherry", "apple"] // // sort // var nArray = [1, 4, 6, 2, 3, 9, 7]; // [1, 4, 6, 2, 3, 9, 7] nArray.sort(); // [1, 2, 3, 4, 6, 7, 9] // 오름차순 정렬 nArray.sort(function (left, right) { return left - right; }); nArray.sort(); // [1, 2, 3, 4, 6, 7, 9] // 내림차순 정렬 nArray.sort(function (left, right) { return right - left; }); nArray.sort(); // [9, 7, 6, 4, 3, 2, 1]
메서드 이름 설명 filter() 특정 조건을 만족하는 요소를 추출해 새로운 배열을 만듭니다 forEach() 배열의 각각의 요소를 사용해 특정 함수를 for in 반복문처럼 실행합니다 every() 배열의 요소가 특정 조건을 모두 만족하는지 확인합니다 map() 기존의 배열의 특정 규칙을 적용해 새로운 배열을 만듭니다 some() 배열의 요소가 특정 조건을 적어도 하나 만족하는지 확인합니다 indexOf() 특정 요소를 앞쪽부터 검색합니다 lastIndexOf() 특정 요소를 뒤쪽부터 검색합니다 var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1]; var sArray = ['a', 'b', 'c', 'd', 'e', 'f', 'd', 'c', 'b', 'a']; array.indexOf(4); // 3 array.indexOf(7); // 6 array.lastIndexOf(4); // 14 array.lastIndexOf(7); // 11 sArray.indexOf('d'); // 3 sArray.lastIndexOf('d'); // 6 // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var sum = 0; var result = ''; narray.forEach(function(element, index, narray) { sum += element; result += index + ': ' + element + ' -> ' + sum + '\n'; }); // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; narray = narray.filter(function(element, index, narray) { return element <= 5; }); // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; function lessThan4(element, index, array) { return element < 4; } function lessThan50(element, index, array) { return element < 50; } narray.every(lessThan4); narray.every(lessThan50); var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1]; var sArray = ['a', 'b', 'c', 'd', 'e', 'f', 'd', 'c', 'b', 'a']; array.indexOf(4); // 3 array.indexOf(7); // 6 array.lastIndexOf(4); // 14 array.lastIndexOf(7); // 11 sArray.indexOf('d'); // 3 sArray.lastIndexOf('d'); // 6 // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var sum = 0; var result = ''; narray.forEach(function(element, index, narray) { sum += element; result += index + ': ' + element + ' -> ' + sum + '\n'; }); sum; result; // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var resultArray = narray.filter(function(element, index, narray) { return element <= 5; }); resultArray; // [1, 2, 3, 4, 5] // //----------------------- // var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; function lessThan4(element, index, array) { return element < 4; } function lessThan50(element, index, array) { return element < 50; } // // every // narray.every(lessThan4); narray.every(lessThan50); // // some // narray.some(lessThan4); narray.some(lessThan50); var narray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var resultArray = narray.map(function (element) { return element + 100; }); resultArray; // [101, 102, 103, 104, 105, 106, 107, 108, 109, 110] // // reduce / reduceRight // var narray = [1, 2, 3, 4, 5]; var result = ''; narray.reduce(function(previousValue, currentValue, index, narray) { result += previousValue + ': ' + currentValue + ' : ' + index + '\n'; }); var narray = [1, 2, 3, 4, 5]; var result = ''; narray.reduceRight(function(previousValue, currentValue, index, narray) { result += previousValue + ': ' + currentValue + ' : ' + index + '\n'; });
연관 배열
- 연관 배열에는 숫자 인덱스가 존재하지 않음
- Object를 일반적으로 사용
- 새원소가 추가될 때마다 배열이 자동으로 확장
var associateArray = new Object(); associateArray["one"] = "ONE"; associateArray["two"] = "TWO"; associateArray; // Object {one: "ONE", two: "TWO"} associateArray.one; // "ONE" associateArray.two; // "TWO"
Date 객체
- 날짜와 시간을 표시하는 객체
- Date 객체를 통개 날짜를 생성하고 년, 월, 일, 시, 분, 초 등의 값에 접근 할 수 있음
- 인자를 지정하지 않고 생성하면 시스템의 현재 날짜값과 시각값으로 초기화
var dateNow = new Date(); var nowDate = new Date("March 15, 2014 12:34:56"); var newDate = new Date(2014, 6, 4); var newDate = new Date(2014, 6, 4, 2, 34, 23); newDate.toLocaleString(); // "2014년 7월 4일 오전 12:00:00"
Math 객체
- 수학과 관련된 속성과 메서드를 갖는 객체
- 자바스크립트 기본 내장 객체 중 유일하게 생성자 함수를 사용하지 않는 객체
- Math 객체는 생성자 함수가 아니라 그냥 객체
- Math 함수로 넘겨진 모든 인자는 변수의 종류와 관계없이 먼저 숫자로 변환
- 프로그래매가 직접 변환할 필요 없다
- Math 삼각함수
- sin, cos, tan, acos, asin, atan, atan2
- Math 반올림, 올림, 내림 기타...
- 랜덤 메소드
- Math.random
- 0과 1사이의 값 생성
- Math.random
-
val nVal = -3.45; var pVal = Math.abs(nVal); // 올림값 nVal = 3.45; Math.ceil(nVal); nVal = -3.45; Math.ceil(nVal); // 내림 nVal = 3.45; Math.floot(nVal) nVal = -3.45; Math.floot(nVal) // 반올림 nVal = 3.45; Math.round(nVal); // 자연로그 Math.exp(4); // 수의 멱승 Math.pow(3,2); Math.min(1, 2, 3); Math.max(1,2,3,4); // 난수 Math.random();
RegExp
- 정규표현식은 패턴을 형성하는 문자들의 집합으로 문자열 내에서 검색, 대체, 추출 등을 할 때 사용
메서드 이름 설명 test() 정규 표현식과 일치하느 문자열이 있으면 true를 아니면, false를 반환합니다 exec() 정규 표현식과 일치하는 문자열을 반환합니다 메서드 이름 설명 match(regExp) 정규 표현식과 일치하는 부분을 반환합니다 replace(regExp, replacement) 정규 표현식과 일치하는 부분을 새로운 문자열로 바꿉니다 search(regExp) 정규 표현식과 일치하는 부분의 위치를 반환합니다 split(regExp) 정규 표현식을 기준으로 문자열을 잘라 배열을 반환합니다 플래그 문자
정규 표현식 기호 설명 g 전역 비교룰 수행합니다 i 대소문자를 가리지 않고 비교합니다 m 여러 줄의 검사를 수행합니다 앵커 문자
정규 표현식 문자 설명 ^ABC 맨 앞 문자가 ABC ABC$ 맨 뒤 문자가 ABC // 정규 표현식 객체의 생성 // 2가지 방법 var regExp1 = new RegExp('text'); var reqExp2 = /text/; var re = /JavaScript rules/; var str = "JavaScript rules"; re.test(str); // true // i : 대소문자 구분 안함 // g : 전역 매칭 // m : 여러줄 매칭 플래그 // RegExp 사용 시, new RegExp('+s', 'g'); // 두번째 인자에 플래그를 전달 var re = /JavaScript rules/i; var re = /JS*/ig; // JS패턴을 찾음, ig플래그로 문자열 전체에서 대소문자 구분 안함 var str = "cfdsJS * (&YJSjs 999JS"; var resultArray = re.exec(str); while (resultArray) { console.log(resultArray[0]); resultArray = re.exe(str); }
정규 표현식 기호 설명 $& 일치하는 문자열 $` 일치하는 부분의 앞부분 문자열 $' 일치하는 부분의 뒷부분 문자열 $1, $2, $3 그룹 정규표현식 자료 참고 할 것
JSON 객체
- ECMAScript 5 부터 정식으로 JSON객체 지원
- JSON JavaScript Object Notation은 자바스크립트 객체의 형태를 가지는 문자열
메서드 이름 설명 JSON.parse() JSON 형식의 문자열을 자바스크립트 객체로 만듭니다 JSON.strigify() 자바스크립트 객체를 JSON 형식의 문자열로 만듭니다 // var object = { name: 'Slipp', team: '04' }; JSON.stringify(object); // var clone = JSON.parse(JSON.stringify(object)); clone;
Date 객체의 JSON 메서드
메서드 이름 설명 toJSON() JSON 문자열로 변경합니다 var date = new Date(); date.toJSON();
예외 처리 Exception handling
- 프로그램이 실행되는 동안 문제가 발생하면 프로그램이 중단됩니다
- 이때 프로그램이 대처할 수 있게 처리하는 것
- Exception
- 프로그램 실행 중 발생하는 오류
- Error
- 프로그래밍 언어의 문법적인 오류
- 예외 처리 2가지 방법
- 기본 예외 처리
- 고급 예외 처리
에러 종류 설명 EvalError eval을 잘못 사용했을 때 RangeError 숫자 값이 법위를 초과했을 때 ReferenceError 잘못된 참조를 사용했을 때 SyntaxError 구문이 잘못되었을 때 TypeError 변수의 타입이 예상한 타입과 다를 때 URIError encodeURI()나 decodeURI()를 잘못 사용했을 때
기본 예외 처리
- 예외가 발생하지 않게 사전에 방지
function whenClick(e) { var event = window.event || e; // 이벤트 객체의 위치가 달라, 브라우저에 무관하게 작성 IE - window.event var msg = ''; msg += 'clientX: ' + event.clientX + '\n'; msg += 'clientY: ' + event.clientY + '\n'; alert(msg); } onclick = whenClick; //
고급 예외 처리
- try, catch, finally 키워드 사용해 예외 처리하는 방법
// 형식 try { } catch (exception) { } finally { } // try { willExcept.ErrorError(); alert("실행 안됨"); } catch (exception) { alert("에러 발생"); } finally { alert('이것은 종료시 항상 호출 됨'); }
예외 객체
- try catch 구문을 사용할 때, catch의 괄호안에 입력하는 식별자가 예외 객체
- 예외 객체의 속성
속성 이름 설명 message 예외 메시지 description 예외 설명 name 예외 이름 number 예외 번호 try { var array = new Array(Number.MAX_VALUE); var item = array[100]; } catch (exception) { var result = ''; for (var i in exception) { result += i + ':' + exception[i] + '\n'; } alert(result); } finally { alert('이것은 종료시 항상 호출 됨'); } // --------------- try { var somearray = null; alert(somearray[17]); } catch (exception) { if (exception instanceof TypeError) { alert("Type Error: " + exception.message); } } // ---------------- try { var somearray = null; alert(somearray[17]); } catch (e) { if (e instanceof TypeError) { alert("Type Error: " + e.message); } } finally { somearray = null; }
예외 강제 발생
- 예외를 강제로 발생시켜야 할 때도 있음
- 예외를 강제로 발생시킬 때, throw 키워드 사용
try { throw '오류 강제 발생'; } catch (exception) { if (exception == '오류 강제 발생') { alert('오류 처리 예정'); } } //---------------------- try { // error 발생 throw { name: "MyErrorType", // 임의의 에러 타입 message: "이크, 에러..", extra: "기타.." }; } catch (exception) { var result = ''; for (var i in exception) { result += i + ':' + exception[i] + '\n'; } alert(result); } //---------------------- // 함수 정의 function divide(a, b) { if (b == 0) { throw '0나누기 에러 발생'; } return a / b; } try { divide(5, 0); } catch (exception) { alert('캡처'); }
이벤트 event
개요
- 이벤트의 역할
- 사용자가 무슨 일을 했는지
- 페이지가 언제 로드 되었는지와 같은 정보를 주는 것
- 이벤트를 캐치하고 처리함으로써 사용자에게 적시에 적절한 서비스를 제공
- 자바스크립트에서 이벤트는 언어가 아니라 객체와 관련이 있음
- 동작 중인 브라우저에 구현된 DOM에 따라 달라짐
- 특정 이벤트가 발생했을 때의 기본 행동은 정해져 있음
- 이벤트를 변경해서 기능을 변경하거나 추가할 수 있음
- 이벤트의 기본 처리 방식을 확장하는 것
- HTML객체 태그
- 자바스크립트 코드 블럭 또는 파일 내에서 이루어 짐
- 이벤트 개념 세가지로 구분
- 사용자 인터페이스(마우스, 키보드 등)
- 논리(처리 결과)
- 변경(문서를 수정하는 일)
- 자바스크립트의 이벤트의 종류
- 마우스 이벤트
- 키보드 이벤트
- HTML 프레임 이벤트
- HTML 입력 양식 이벤트
- 유저 인터페이스 이벤트
- 구조 변화 이벤트
- 터치 이벤트
- 이벤트 발생
- 애프리케이션 사용자가 발생
- 애플리케이션 스스로 발생
- 이벤트 모델
- 문서 객체에 이벤트를 연격하는 방법
- DOM Level 단계에 따라 2 가지
- DOL Level 0
- 고전 이벤트 모델
- 인라인 이벤트 모델
- DOM Level 2
- 마이크로소프트 인터넷 익스플로러 이벤트 모델
- 표준 이벤트 모델
- DOL Level 0
이벤트 관련 용어
- 비동기
- 비동기 asynchronous 식 이베트의 구조는 스레드 방식의 애플리케이션 구조와 달리 일반적인 콜백 callback 구조
- 하나의 코드 조각(콜백)이 이벤트 핸들러(처리기) Event Handler 로 등록
- 이벤트가 발생할 때 이 콜백이 실행
- 콜백 붙이기 / 연결하기 / 등록하기
- 콜백을 이벤트 핸들러에 붙인다(또는 연결한다)는 것은 비동기식 이벤트 모델에서 코드가 연결되는 방법
- 이벤트가 발생하면 이벤트 핸들러가 호출
- 등록된 콜백에 대한 참조가 담겨있다
- 콜백이란 함수 참조의 형태를 가진 코드 조각
- 이벤트가 완료되고 나면 이 콜백 호출
- 버블 Bubbling
- 이벤트의 캡처 단계가 지나면 이벤트의 버블 단계 Bubbling 가 발생
- 버블 단계는 이벤트의 발생 장소(사용자가 클릭한 링크 등)에서 시작하여 DOM 트리를 거슬러 문서의 루트까지 올라감
- 캡처 Capturing
- 이벤트의 캡처 단계 Capturing 란 처음으로 발생하는 이벤트 단계
- 이벤트가 시작된 엘리먼트의 위치까지 DOM트리르 따라 내려가는 이벤트로 구성
- 캡처 단계는 오직 W3C 이벤트 모델에서만 발생
- 기본 동작 Default Action
- 사용자가 이벤트 핸들러를 연결했는지 여부와 관계없이 수행되는 브라우저 고유의 동작
- 예)
- 사용자가 링크를 클릭했을 때
- 해당 웹 페이지를 방문하는 것이 브라우저에 의한 기본동작
- 사용자가 링크를 클릭했을 때
- 이벤트 Event
- 이벤트란 웹 패이지 안에서 구동(시작)되는 동작
- 일반적으로 사용자에 의해 시작
- 마우스 움직이기
- 키보드 누리기
- 등
- 사용자와 상호작용 없이 발생할 수도 있음
- 페이지 로딩
- 에러 발생
- 등
- 자바스크립트 이벤트는 캡처링와 버블링 이라는 두 단계에 걸쳐 실행
- 이벤트 핸들러(처리기) Event Handler
- 이벤트 핸들러란 이벤트가 구동될 때마다 호출되는 코드
- 만일 이벤트 핸들러에 등록되어 있는 콜백이 없다면 기본 동작 외에는 아무것도 일어나지 않는다
- 이벤트 명(이름) / 이벤트 타입 Event Name / Event Type
- 1
- 이벤트 모델
- 문서 객체에 이벤트를 연격하는 방법
- DOM Level 단계에 따라 2 가지
- DOL Level 0
- 고전 이벤트 모델
- 인라인 이벤트 모델
- DOM Level 2
- 마이크로소프트 인터넷 익스플로러 이벤트 모델
- 표준 이벤트 모델
- DOL Level 0
- 예
- window.onload = function( ) { };
- load를 이벤트 명(이름) Event Name 또는 이벤트 타입 Event Type
- onload를 이벤트 속성
- 이벤트 속성에 할당한 함수를 이벤트 핸들러 Event Handler
window.onload = function() { // 변수를 선언 var hplogo = document.getElementById('hplogo'); // 이벤트 연결 function whenClick() { alert('Mouse Click'); } hplogo.onclick = whenClick; } // // --------------------- // // google 접속 // www.google.com var hplogo = document.getElementById('hplogo'); function whenClick() { alert('Mouse Click'); } hplog.onclick = whenClick;
이벤트 전달
- 이벤트 전달이란?
- 어떠한 이벤트가 먼저 발생해 어떤 손서로 발생하는지 정하는 것
- 이벤트 전달 순선는 이벤트 버블링 방식을 따름
이벤트 버블링 Event Bubbing
- 자식 노드에서 부모 노드 순으로 이벤트를 실행
<!DOCTYPE html> <html> <head> <title>Event Bubbling Example</title> </head> <body> <div id="myDiv">Click Me</div> </body> </html>
- div 엘레멘트에서 클릭 했을 때
- <div>
- <body>
- <html>
- document
- 아래 그림 참고
이벤트 캡처링 Event Capturing
- 이벤트가 부모 노드에서 자식 노드 순으로 실행
- div 엘레멘트에서 클릭 했을 때
- document
- <html>
- <body>
- <div>
- 아래 그림 참고
DOM 이벤트 전달 DOM Event Flow
- DOM Level 2 이벤트에서 지정한 이벤트 전달은 3단계
- 이벤트 캡처링 단계
- 이벤트 캡처가 필요한 경우, 우선 인터셉터 할 수 있는 기회 제공
- 실제 대상 이벤트
- 이벤트 버블링 단계
- 이벤트에 대한 최종 응답을 버블링
- 이벤트 캡처링 단계
이벤트 버블 취소하기
- 이벤트가 오직 그 대상에서만 발생할 뿐 그 부모로는 더 이상 전파되지 않기 원할 경우
- 이번트 버블 과정을 멈춰야 함
- 이벤트의 버블(또는 캡처)을 멈추는 것은 유용함
- 인터넷 익스플로러와 그 외 모든 브라우저와는 다른 형태로 제공
// 이벤트 버블링 정지 function stopBubble (e) { // 이벤트 객체가 제공되었다면, IE 아님 if (e) { // W3C stopPropagation() 메서드 지원 e.stopPropagation(); } else{ // 인너텟 익스플로러 방식 사용 window.event.cancelBubble = true; }; }
브라우저의 기본 동작을 덮어쓰기
- 브라우저의 기본동작 정지
- preventDefalut() / returnValue = false
// 브라우저의 기본 동작이 발생하는 것을 막는 일반 함수 function stopDefault(e) { // 브라우저의 기본 동작을 막는다(W3C) if ( e && e.preventDefalut ) { e.preventDefault(); } else { // IE 브라우저의 동작을 중지시키는 방법 window.event.returnValue = false; } return false; } // a link의 브라우저의 기능을 막음 var a = document.getElementsByTagName('a'); for(var i = 0, max = a.length; i < max; i++) { a[i].onclick = function(e) { document.title = this.href; alert(this.href); return stopDefault(e); } }
this 사용
- this 키워드는 편리함을 위해 사용
// click 처리기 function handleClick(e) { console.log(e.type + ' - ' + this.tagName); this.style.backgroundColor = 'blue'; this.style.color = 'white'; } // click 처리기 function handleClickStopBubble(e) { console.log(e.type + ' - ' + this.tagName); this.style.backgroundColor = 'blue'; this.style.color = 'white'; stopBubble(e); } // mouseover 처리기 function handleMouseOver(e) { console.log(e.type + ' - ' + this.tagName); this.style.backgroundColor = 'blue'; this.style.color = 'white'; } // mouseout 처리기 function handleMouseOut(e) { console.log(e.type + ' - ' + this.tagName); this.style.backgroundColor = 'white'; this.style.color = 'black'; } // 이벤트 버블링 정지 function stopBubble (e) { // 이벤트 객체가 제공되었다면, IE 아님 if (e) { // W3C stopPropagation() 메서드 지원 e.stopPropagation(); } else{ // 인너텟 익스플로러 방식 사용 window.event.cancelBubble = true; }; } // function changeHandler () { // 엘리먼트를 찾고 각각에 click 처리기를 연결 document.getElementsByTagName('html')[0].onclick = handleClick; document.getElementsByTagName('html')[0].onmouseover = handleMouseOver; document.getElementsByTagName('html')[0].onmouseout = handleMouseOut; document.getElementsByTagName('body')[0].onclick = handleClick; document.getElementsByTagName('body')[0].onmouseover = handleMouseOver; document.getElementsByTagName('body')[0].onmouseout = handleMouseOut; document.getElementsByTagName('div')[0].onclick = handleClick; document.getElementsByTagName('div')[0].onmouseover = handleMouseOver; document.getElementsByTagName('div')[0].onmouseout = handleMouseOut; } // function changeHandlerBubblingCancel () { // 엘리먼트를 찾고 각각에 click 처리기를 연결 document.getElementsByTagName('html')[0].onclick = handleClickStopBubble; // document.getElementsByTagName('html')[0].onmouseover = handleMouseOver; // document.getElementsByTagName('html')[0].onmouseout = handleMouseOut; document.getElementsByTagName('body')[0].onclick = handleClickStopBubble; // document.getElementsByTagName('body')[0].onmouseover = handleMouseOver; // document.getElementsByTagName('body')[0].onmouseout = handleMouseOut; document.getElementsByTagName('div')[0].onclick = handleClickStopBubble; // document.getElementsByTagName('div')[0].onmouseover = handleMouseOver; // document.getElementsByTagName('div')[0].onmouseout = handleMouseOut; } // window.onload = changeHandler;
이벤트 리스너 연결하기
DOM Level 0 이벤트 리스너 연결
DOM Level 0 - 고전 이벤트 모델
window.onload = function(){ … };
- 장점
- 간단하며 일관적
- 어떤 브라우저를 사용하든 관계없이 동일한 동작 보장
- 이벤트를 다룰 때, this 키워드가 현재 엘리먼트 참조
- 단점
- 캡처 단계와 버블 단계 모두에 대해서가 아니라, 오직 이벤트 버블 단계에 대해서만 작동
- 어떤 엘리먼트에 대해 한 번에 단 하나의 이벤트 핸들러만 연결
- 이벤트 객체 전달인자는 인터넷 익스플로러가 아닌 브라우저에서만 사용 가능
// 첫번째 <form> 엘리먼트를 찾아서 'submit' 이벤트 핸들러를 붙인다 document.getElementsByTagName("form")[0].onsubmit = function(e){ // 모든 폼 제출 시도를 중단 return stopDefault( e ); }; // <body> 엘리먼트에 keypress 이벤트 핸들러를 붙인다 document.body.onkeypress = myKeyPressHandler; // 페이지에 load 이벤트 핸들러를 붙인다 window.onload = function(){ ... }; //----------------------
DOM Level 0 - 인라인 이벤트 모델
- HTML 페이지의 가장 기본적인 이벤트 연결 방법
- 인라인 이벤트 모델
// <body> <h1 onclick='alert("클릭")'>Click</h1> </body> //--------------------------- // 인라인 이벤트 모델 // 이벤트 연결 <!DOCTYPE html> <html> <head> <title>인라인 이벤트 모델</title> <script> function whenClick(e) { alert('클릭'); } </script> </head> <body> <h1 onclick="whenClick(event)">Click Me</h1> </body> </html> // 이벤트 제거 <script> window.onload = function() { // 이베트를 연결 document.getElementById('firstForm').onsubmit = function() { return false; } } </script> //--------------------------- // 인라인 이벤트 모델을 사용할 때는 onsubmit이벤트 속성에 return 함수()를 입력 // 이벤트 제거 <script> function whenSubmit() { // 서버 전송 return false; } </script> <form onsubmit="return whenSubmit()"> </form>
addEvent / removeEvent
- 인터넷 익스플로러 이벤트 추가 삭제
- addEvent
- removeEvent
DOM Level 0
// addEvent 함수를 사용하는 예 // // 페이지 로딩이 완료되기를 기다린다 addEvent( window, "load", function(){ // 사용자에게 keypresses 이벤트가 들어오기를 기다린다 addEvent( document.body, "keypress", function(e){ // 마일 사용자가 Spacebar + Ctrl 키를 누를 경우 if ( e.keyCode == 32 && e.ctrlKey ) { // 특별한 폼을 표시 this.getElementsByTagName("form")[0].style.display = 'block'; // 그 외에 다른 이상한 일이 일어나지 않게 된다 e.preventDefault(); } }); }); // //--------------------------------------------------------------- // written by Dean Edwards, 2005 // with input from Tino Zijdel, Matthias Miller, Diego Perini // http://dean.edwards.name/weblog/2005/10/add-event/ function addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else { // assign each event handler a unique ID if (!handler.$$guid) handler.$$guid = addEvent.guid++; // create a hash table of event types for the element if (!element.events) element.events = {}; // create a hash table of event handlers for each element/event pair var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; // store the existing event handler (if there is one) if (element["on" + type]) { handlers[0] = element["on" + type]; } } // store the event handler in the hash table handlers[handler.$$guid] = handler; // assign a global event handler to do all the work element["on" + type] = handleEvent; } }; // a counter used to create unique IDs addEvent.guid = 1; function removeEvent(element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else { // delete the event handler from the hash table if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } } }; function handleEvent(event) { var returnValue = true; // grab the event object (IE uses a global event object) event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); // get a reference to the hash table of event handlers var handlers = this.events[event.type]; // execute each event handler for (var i in handlers) { this.$$handleEvent = handlers[i]; if (this.$$handleEvent(event) === false) { returnValue = false; } } return returnValue; }; function fixEvent(event) { // add W3C standard event methods event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; }; fixEvent.preventDefault = function() { this.returnValue = false; }; fixEvent.stopPropagation = function() { this.cancelBubble = true; };
DOM Level 2 이벤트 리스너 연결
Dom Level 2 연결 - 마이크로소프트 인터넷 익스플로러 이벤트 모델
- 대상 엘리먼트에 원하는 만큼 얼마든지 많은 이벤트를 연결할 수 있음
- 기존의 연결된 핸들러를 전혀 덮어쓰지 않음
- 2가지 메서드
- attachEvent(eventProperty, eventHandler)
- detachEvent(eventProperty, eventHandler)
- 1
// <script> window.attachEvent('onload', function() { }); </script> // // ---------------------------- <!DOCTYPE html> <html> <head> <script> // 윈도우가 로드 될때 window.attachEvent('onload', function() { // myHeader를 가져옴 var header = document.getElementById('myHeader'); // 이벤트를 연결합니다. header.attachEvent('onclick', function () { alert('클릭1'); }); header.attachEvent('onclick', function () { alert('클릭2'); }); header.attachEvent('onclick', function () { alert('클릭3'); }); } </script> </head> <body> <h1 id='myHeader'>Click</h1> </body> </html>
- 장점
- 대상 엘리먼트에 원하는 만큼 얼마든지 많은 이벤트를 연결할 수 있음
- 기존의 연결된 핸들러를 전혀 덮어쓰지 않음
- 대상 엘리먼트에 원하는 만큼 얼마든지 많은 이벤트를 연결할 수 있음
- 단점
- 인터넷 익스플로러에서는 이벤트의 버블 단계 만을 지원
- 이벤트 처리기는 처리 함수 내부에서 this키워드는 window객체를 참조
- 이벤트 객체는 오직 window.event 매개 변수를 통해서만 가능
- 이벤트 이름을 'on-타입' 형식으로 지명
- click -> onclick
- 인터넷 익스플로러에서만 사용
// 첫번째 <form> 엘리먼트를 찾아서 'submit' 이벤트 핸들러를 붙인다 document.getElementsByTagName("form")[0].attachEvent('onsubmit',function(){ // 모든 폼 제출 시도를 막음 return stopDefault(); },); // <body> 엘리먼트에 keypress 이벤트 핸들러를 붙인다 document.body.attachEvent('onkeypress', myKeyPressHandler); // 페이지에 load 이벤트 핸들러를 붙인다 window.attachEvent('onload', function(){ ... });
DOM Level 2 연결 - 표준 이벤트 모델
- addEventListener / removeEventListener
- 장점
- 캡처와 버블 단계를 모두 지원
- addEventListener의 마지막 매개 변수를 설정하여 이벤트 처리 과정을 전환(false 버블, true 캡처)
- 이벤트 처리기는 처리 함수 내부에서 this키워드는 현재 엘리먼트를 참조
- 이벤트 객체는 처리 함수의 첫 번째 전달 인자로 얻을 수 있음
- 대상 엘리먼트에 원하는 만큼 얼마든지 많은 이벤트를 연결할 수 있음
- 기존의 연결된 핸들러를 전혀 덮어쓰지 않음
- 캡처와 버블 단계를 모두 지원
- 단점
- 인터넷 익스플로러에서는 작동하지 않음
- 인터넷 익스플로러에서는 attachEvent 함수를 대신 사용
// 첫번째 <form> 엘리먼트를 찾아서 'submit' 이벤트 핸들러를 붙인다 document.getElementsByTagName("form")[0].addEventListener('submit',function(e){ // 모든 폼 제출 시도를 막음 return stopDefault( e ); }, false); // <body> 엘리먼트에 keypress 이벤트 핸들러를 붙인다 document.body.addEventListener('keypress', myKeyPressHandler, false); // 페이지에 load 이벤트 핸들러를 붙인다 window.addEventListener('load', function(){ ... }, false);
addEventListener와 removeEventListener
- 이벤트 추가 삭제
- addEventListener
- removeEventListener
- W3C
// 이벤트 추가 <!DOCTYPE html> <html> <head> <script> // 윈도우가 로드 될때 window.onload = function() { // myHeader를 가져옴 var header = document.getElementById('myHeader'); // 이벤트를 연결합니다. header.addEventListener('click', function () { this.innerHTML += '+'; }); header.addEventListener('click', function () { alert('클릭2'); }); header.addEventListener('click', function () { alert('클릭3'); }); }; </script> </head> <body> <h1 id='myHeader'>Click</h1> </body> </html> // 이벤트 제거 <script> </script> //-------------------------------------- <!DOCTYPE html> <html> <head> <script> // // 윈도우가 로드 될때 // window.onload = function() { // // myHeader를 가져옴 // var header = document.getElementById('myHeader'); // // 이벤트를 연결합니다. // header.addEventListener('click', function () { // this.innerHTML += '+'; // }); // header.addEventListener('click', function () { alert('클릭2'); }); // header.addEventListener('click', function () { alert('클릭3'); }); // }; </script> <script> // 윈도우가 로드 될때 window.onload = function() { // myHeader를 가져옴 var header = document.getElementById('myHeader'); // 이벤트를 연결합니다. if (header.attachEvent) { var handler = function() { window.event.srcElement.style.color = 'red'; window.event.srcElement.detachEvent('onclick', handler); } header.attacheEvent('onclick', handler); } else{ // 이벤트를 연결합니다. var handler = function() { this.style.color = 'red'; this.detachEvent('onclick', handler); } header.addEventListener('click', handler); header.addEventListener('click', handler); }; // header.addEventListener('click', function () { alert('클릭2'); }); // header.addEventListener('click', function () { alert('클릭3'); }); }; </script> </head> <body> <h1 id='myHeader'>Click</h1> </body> </html>
브라우저 객체 모델 BOM (Browser Object Model)
- BOM은 자바스크립트 프로그램이 동작하는 브라우저 컨텍스트에서 상속된 객체 집합
- window, location, navigation, history, screen, document
- 자바스크립트에서 접근 및 사용이 가능한 기본 웹 객체들의 집합
- document 객체와 관련된 객체의 집합을 DOM Document Object Model 이라 함
BOM 계층구조
window 객체
- 전역개체
- 브라우저 기반 자바스크립트의 최상위 객체
- 직접 명시하기보다는 묵시적으로 사용하는 것이 일반적
- alert, prompt 같은 함수들은 객체 모델과는 상관없이 '독립적'처럼 보이지만 window 객체의 일부
- 전역 변수, 객체 모델 내의 다른 객체와 관련이 없는 객체들도 두 번째 레벨 객체에 속함
- 상태 표시줄(status bar)의 내용 변경
- 윈도우 열기와 닫기
- 기존 윈도우의 크기 변경
- window 객체의 메소드와 프로퍼티 아래 네 가지로 나뉨
- 새 윈도우의 생성 및 관리
- 기존 윈도우의 변경
- 타이머 역할
- BOM 객체들의 최상위 객체 역할
// window 객체의 생성과 메서드 var i = 1; var (var key in window) { console.log(i + ' ' + key + ': ' + window[key]); i++; }
alsert, confire, prompt 대화상자 종류
- allert
- 웹페이이지에 접근하는 사람에게 메시지를 전달하는 가장 빠른 방법
- 화면에 나타낼 메시지 문자열은 인자로 넘겨줌
- alert('이것은 메시지입니다');
- confirm
- 질문과 2개의 버튼(OK(확인), Cancel(취소) 버튼) 화면에 표시
- 화면에 나타낼 메시지 문자열은 인자로 넘겨줌
- var result = confirm('끝내겠습니까?');
- prompt
- 질문과 함께 문자열을 입력하도록 요구
- 2개의 버튼(OK(확인), Cancel(취소) 버튼) 화면에 표시
- 인자로는 화면에 나타낼 메시지 문자열과 기본 입력 문자열값(사용자가 입력하는 문자열의 기본 값)의 두 가지를 지정
- allert
새 윈도우 객체 생성
- 새로운 window 객체를 생성
- window 객체의 윈도우 생성 메서드
메서드 이름 설명 oepn(URL, name, features, replace) 새로운 window 객체를 생성
window 형태 옵션
옵션 이름 설명 입력할 수 있는 값 height 새 윈도우의 높이 픽셀 값 width 새 윈도우의 너비 픽셀 값 location 주소 입력창의 유무 yes, no, 1, 0 menubar 메뉴의 유무 yes, no, 1, 0 resizable 화면 크기 조절 가능 여부 yes, no, 1, 0 status 상태 표시줄의 유무 yes, no, 1, 0 toolbar 툴바의 유무 yes, no, 1, 0
// open() 메서드 window.open(); // open() 메서드의 옵션 window.open('http://www.google.com', 'child', 'width=600, height=300', true); // 변수 선언 var child = window.open('', '', 'width=300, height=200'); // 화면 표시 if (child) { child.document.write('<h1>부모창에서</h1>'); } else { alert('팜업 차단을 해제해주세요'); }
타이머 메서드
- 웹페이지에 동적 요소를 추가하는 방법 중 하나
- 2가지 종류
- 일회용
- setTimeout 메서드 사용
- 한번만 동작
- 인자는 2개
- 타이머에 지정한 시간이 경과된 후 실행될 함수 리터럴 또는 함수명
- 타이머가 카운트 다운할 시간값
- 시간값은 밀리 초 단위로 지정
- 함수로 전달하고자 하는 매개 변수는 맨 마지막에 쉽표(,)로 구분하여 나열
- 타이머 취소시
- clearTimeout 메서드 사용
- timer 메소든느 타임아웃 식별자를 반환
- 주기적
- 특정 주기로 타이머를 반복
- setInterval 메서드 사용
- 인자
- 함수 리터럴 또는 함수명
- 타이머 주기
- 타이머 취소시
- clearInterval
- 일회용
window 객체의 타이머 메서드
메서드 이름 설명 setTimeout(function, millisecond) setInterval(function, millisecond) clearTimeout(id) clearInterval(id) // 타이머 메서드 // 윈도우가 로드될 때 //window.onload = function () { function three() { var child = window.open('', '', 'whidth=300, height=300'); child.document.write('<h1>3초 후 이 페이지는 종료됩니다</h1>'); // 3초 후에 함수를 실행합니다 window.setTimeout(function () { child.close(); }, 3000); }; // 특정 주기 타이머 메서드 // 타이머 정지 메서드 // 윈도우가 로드될 때 //window.onload = function () { function three() { var intervalID = setInterval(function () { document.body.innerHTML += '<p>' + new Date() + '</p>'; }, 1000); // 5초 후 함수를 실행합니다. setTimeout(function () { // 타이머를 종료함니다 clearInterval(intervalID); alert('타이머 종료'); }, 10000); };
window 객체의 기본 메서드
- 자신의 형태와 위치를 변경할 수 있음
window 객체의 메서드
메서드 이름 설명 moveBy(x, y) 윈도우의 위치를 상대적으로 이동합니다 moveTo(x, y) 윈도우의 위치를 절대적으로 이동합니다 resizeBy(x, y) 윈도우의 크기를 상대적으로 지정합니다 resizeTo(x, y) 윈도우의 크기를 절대적으로 지정합니다 scrollBy(x, y) 윈도우 스크롤의 위치를 상대적으로 이동합니다 scrollTo(x, y) 윈도우 스크롤의 위치를 절대적으로 이동합니다 focus() 윈도우에 초점을 맞춥니다 blur() 윈도우에 초점을 제거합니다 close() 윈도우를 답습니다 // 변수 선언 var child = window.open('', '', 'width=300, height=200'); child.moveTo(0, 0); // 1초 마다 함수를 싷행합니다 var intervalID = setInterval(function() { child.moveBy(10, 10); }, 1000); // 타이머 해제 setTimeout(function () { // 타이머를 종료 clearInterval(intervalID); }, 10000);
screen 객체
- 운영체제 화면의 속성을 가지는 객체
// screen 객체의 속성 출력 for(var key in screen) { console.log(key + ': ' + screen[key]); }
screen 객체의 속성
속성 이름 설명 width 화면의 너비 height 화면의 높이 availWidth 실제 화면에서 사용 가능한 너비 availHeight 실제 화면에서 사용 가능한 높이 colorDepth 사용 가능한 색상 수 pixelDepth 한 픽셀당 비트 수
var child = window.open('', '', 'whidth=300, height=300'); var width = screen.width; var height = screen.height; child.moveTo(0, 0); child.resizeTo(width, height); // // 1초 마다 함수를 싷행합니다 var intervalID = setInterval(function() { child.resizeBy(-30, -30); child.moveBy(15, 15); }, 2000); // 타이머 해제 setTimeout(function () { // 타이머를 종료 clearInterval(intervalID); }, 20000);
location 객체
- location 객체의 프로퍼티는 전부 페이지의 로케이션과 관련
- 브라우저의 주소 표시줄과 관련된 객체
- 페이지를 이동할 때 많이 사용
- assign() 메서드와 replace() 메서드 모두 페이지 이동
- assign() 와 다르게 replace()는 뒤로 가기 버튼을 사용할 수 없다
- assign() 메서드와 replace() 메서드 모두 페이지 이동
// location 객체의 속성 출력 for(var key in location) { console.log(key + ': ' + location[key]); }
location 객체
속성 이믈 설명 hash URL에서 해시마크(#) 뒤에 오는 문자열 host 호스트명과 포트 번호 hostname 호스트명 href URL 전체 pathname 도메인명 다음에 오는 경로명 port 포트 번호 protocol 프로토콜 search 질의 문자열(요청문자열) target URL의 target명 location 객체의 메서드
메서드 이름 설명 assign(link) 현재 위치를 이동함니다 reload() 새로 고칩니다 replace(link) 현재 위치를 이동합니다 // 페이지 이동 location = 'http://www.slipp.net'; location.href = 'http://www.slipp.net'; location.assign('http://www.slipp.net'); location.replace('http://www.slipp.net'); // 현재 페이지 새로 고침 방법 location = location; location.href = location.href; location.assign(location); location.replace(location); location.reload();
navigator 객체
- 웹 페이지를 실행하고 있는 브라우저에 대한 정보를 가지고 있음
// navigator 객체의 속성 출력 for(var key in navigator) { console.log(key + ': ' + navigator[key]); }
navigator 객체의 속성
속성 이름 설명 appCodeName 브라우저의 코드명 appName 브라우저의 이름 appVersion 브라우저의 버전 platform 사용 중인 운영체제의 시스템 환경 userAgent 브라우저의 전체적인 정보
history 객체
- 브라우저가 로드했던 페이지의 히스토리를 저정
- go 메서드에 숫자를 인자로 주어 원하는 페이지로 이동
- ( - ) 음수값을 주면 이전 페이지로 이동
// history 객체의 속성 출력 for(var key in navigator) { console.log(key + ': ' + history[key]); } // - 이전페이지로 이동 history.go(-1); history.go(-4); history.go(1); history.go(3);
문서 객체 모델 DOM (Document Object Model)
- W3C에서 DOM에 대해 아래와 같이 설명
- 문서 객체 모델(DOM)은 플랫폼과 언어에 중립적인 인터페이스로 프로그램과 스크립트를 사용해서 동적으로 접근할 수 있도록 하며, 문서의 내용, 구조, 스타일을 변경할 수 있다. 그리고 문서에 추가적인 작업을 할 수 있으며, 처리 결과를 현재 페이지에 나타낼 수 있다
- DOM Level 1
- 1998년 권고안 발표
- DOM에 대한 인프라스트럭처(DOM 향후 버전에서 기본 기능으로 사용할 수 있는 스키마와 API)를 정의하는데 도움
- DOM호환 사용자 에이전트(예, 웹브라우저)에 필요한 각 권고안의 핵심 컴포넌트를 수립하는데 도움
- 모든 스펙을 분리된 옵션모듈로 발표
- 이러한 방법 덕분에 빠른 도입이 가능
- 핵심 엘리먼트의 일관성을 유지
- DOM Level 2
- 2000년 발표
- Level 1 확장
- CSS(Cascading Style Sheet)를 추가
- XML 권고안의 네임스페이스(namespace) 지원도 추가
- DOM Level 3
- 2004년 발표
- 앞서 발표된 릴리즈를 확장하고 개선한 것
- XML에 대한 지원을 늘림
- 웹서비스 지원 확장을 위한 모듈 추가
두 가지 인터페이스
- DOM API 두가지
- Core API
- 언어와 모델에 독립적인 API
- 자바스크립크뿐만 아니라 다른 언어를 사용해서도 구현 할 수 있음
- XHTML뿐만 아니라 다른 XML기반 모델에도 사용
- 공용 API
- 모든 표준 XML 폼에 사용
- Node, nodeList, Attr, Element, Document와 같은 객체들로 구성
- 데이터 타입의 기본 집함을 제공
- 에이전트(브라우저)의 필수 지원 사항을 정해 높음
- HTML API
- 객체지향적
- 계층구조
- HTML에 해당하는 객체를 만들어 놈
- HTML 문서
- HTMLDocumentElement
- body
- HTMLBodyElement
- HTML 문서
- BOM API 와 DOM HTML API의 차이점
- DOM HTML API 가 W3C 주도하에 여러 브라우저에서 호환되는 목표로 설계
- W3C는 기존의 Core API와의 호환성을 높이기 위해 API를 확장
- HTML API는 DOM Level 1과 2에서만 볼 수 있음
- Level 3의 추가 및 변동 사항은 코어 API와 관련 된 것들
- DOM Level 3은 HTML API에 직접적인 영향을 주지 않음
- Core API
DOM 호환 브라우저
- 브라우저간 완벽한 호환은 현실적으로 불가능
- 대부분의 브라우저는 Core API 와 HTML API를 모두 지원하도록 구현
- 대부분의 브라우저는 표준을 거의 준수하기는 하지만 브라우저별로 미묘한 차이점
DOM HTML API
- Core API는 유효한 XML(XHTML 포함)에서만 동작
- 유효한 XHTML과 HTML에서 동작
- HTML API 객체
- Core Node 객체뿐만 아니라
- 기본 HTML 엘리먼트의 프로퍼티와 메소드도 상속
HTML 객체와 HTML 객체의 프로퍼티
- 실제는 클스라기 보다 인터페이스의 집합
- 현재 존재하거나 새로 생성된 페이지 객체에만 접근
- 대부분의 HTML 인터페이스 객체는 엘리먼트와 노드 객체의 프로퍼티와 메서드를 상속
- HTMLElement
- id, title, lang, dir, className과 같은 프로퍼티
- 각 interface 객체의 이름은 HTML의 폼 엘리먼트 이름을 본따서 만듬
- HTMLFormElement - HTML form 엘리먼트의 인터페이스 객체
- HTMLParagraphElement - HTML 문단 테그(p)에 대한 객체
- HTMLImageElement - HTML image
- HTMLDivElement - HTML div
- HTMLTableElement - HTML table
- HTMLRableRowElement - HTML tr
- HTMLCollection
- HTMLOptionCollections
- HTMLDocumentElement - Core Model의 document 객체의 기능을 상속받음
- ...
- 일부 DOM HTML 인터페이스 객체는 관련 페이지 엘리먼트를 생성, 제거, 수정할 수 있는 메서드를 제공
HTML 객체 접근과 브라우저별 차이점
페이지 엘리먼트의 DOM HTML 표현에 접근하는 방법
- 특정 식별자(id)를 지정한 후에 document의 getElementById 메서드를 사용
- 엘리먼트간의 관계를 사용해서 접근하는 방법
- getElementByName 메서드를 사용해서 엘리번트의 이름을 매개 변수로 넘겨 사용
- 동일한 이름의 노드 컬렉션이 들어있는 nodeList를 반환
- 반환한는 nodeList는 브라우저에 따라 차이
// 방법 1 <div id="div1"> ... </div> // getElementById 메서드 사용 var div1 = document.getElementById("div1"); // //---------------------------- // 방법 2 <form> <input type="text" /> </form> // document 객체의 폼 컬렉션을 통해서 폼 필드에 접근 document.forms[0].fields[0]; // //---------------------------- // 방법 3 <div id="div1" name="divName1"> ... </div> // getElementByName 메서드를 사용 document.getElementByName("divName1");
Core API
- HTML보다 XML기반의 XHTML을 사용
- DOM Core API 사용도 늘어남
- 예
- 웹 페이지는 head와 body 있음
- body에는 hi, div 가 있음
- div하단에는 p, p 가 존재
- 이를 도식화하면 아래와 같음
- DOM은 이런한 트리 노드에 접근할 수 있는 표준을 제공
- 여러 계층을 찾아 다니거나
- 특정 종류의 태그를 검색함으로 가능
- 트리 내의 노드를 읽을 수 있음
- 새로운 노드를 만들 수 있음
DOM 트리
- 다른 엘리먼트에 포함되어 있는 엘리먼트를 자식 노드
- 동등한 레벨에 속해있는 다른 엘리먼트를 형제 노드
- 그 상위 레벨의 엘리먼트를 부모 노드
- 아래 문서와 엘리먼트의 계층구조
<!DOCTYPE html> <html> <head> <title>Slipp Study - DOM</title> </head> <body> <div id='divId'> <h1>Slipp Study - DOM study</h1> <p>문서 트리를 더 잘 이해하기 위해서 head, body, title, div 엘리먼트로 이루어지 웹페이지를 가정해보자. 이 예에서 div내에는 헤더(h1)와 두개의 문단(p)가 존재한다. 첫 번째 문단에는 <i>이첼릭체</i> 부분도 포함되어 있으며, 두 번째 문단에는 그림(이미지)도 포함되어 있다. 아주 일발적인 웹페이지라 할 수 있다.</p> <p>이미지가 있는 두 번째 문단<img src='google.png' alt='google' /></p> </div> </body> </html>
- 위 웹페이지 엘리먼트의 계층구조
document; document.ATTRIBUTE_NODE; for(var key in document) { console.log(document[key]); }; document.images[0]; document.images[0].setAttribute("width", "200"); var div = document.getElementsByTagName("div"); // // document.documentElement .firstChild // head .nextSibling // body .firstChild // div .firstChild // h1 - #text .nextSibling // h1 // XML문서의 공백 버그를 피해가는 방법 function cleanWhitespace (element) { // 엘리먼트가 제공되지 않았으면 HTML 문서 전체에 함수를 적용 element = element || document; // 첫째 자식을 시작점으로 삼는다 var cur = element.firstChild; // 자식 노드가 없을 때까지 계속한다 while (cur != null) { // 이 노드가 텍스트 노드이면서 공백밖에 없는 경우 if (cur.nodeType == 3 && ! /\S/.test(cur.nodeValue)) { // 텍스트 노드를 제거한다 element.removeChild(cur); } else if (cur.nodeType == 1) { // 엘리먼트인 경우 // 하위 단계로 재귀 cleanWhitespace(cur); } cur = cur.nextSibling; // 다음 자직 노드로 이동 } } // cleanWhitespace() document.documentElement .firstChild // head .nextSibling // body .firstChild // div .firstChild // h1
- 노드들의 관계
- 예
<p><strong>Hello</strong> how are you doing?</p>
- 예
- 포인터를 사용하여 DOM 트리 탑색하기
노드의 프로퍼티와 메서드
- Node 객체 프로퍼티와 메서드의 기본 집함을 갖음
프로퍼티 이름 설명 nodeName 객체명, 예, head 엘리먼트에 대한 객체명은 HEAD nodeValue 엘리먼트가 아닌 경우, 객체의 값 nodeType 노드의 종류, 숫자로 표현 parentNode 현재 노드의 부모 노드 childNodes 자식 노드의 NodeList firstChild NodeList에 존재하는 자식 노드 중 첫 번째 노드 lastChild NodeList에 존재하는 자식 노드 중 마지막 노드 previousSibling NodeList에 존재하는 현재 자식 노드의 이전 노드 nextSibling NodeList에 존재하는 현재 자식 노드의 다음 노드 attributes 엘리먼트 속성의 키-값 짝의 목록인 NamedNodeMap(다른걕체에는 적용할 수 없다) ownerDocument 문서 객체 namespaceURI 노드에 대한 네임스페이스 URI prefix 노드에 대한 네임스페이스 프리픽스(prefix) localName 네임스페이스 URI가 존재할 경우 노드에 대한 로컬 이름 <!DOCTYPE html> <html> <head> <title>Slipp Study - DOM</title> <script> // 임의의 색상을 만드는 함수 function randomColor () { r=Math.floor(Math.random() * 255).toString(16); g=Math.floor(Math.random() * 255).toString(16); b=Math.floor(Math.random() * 255).toString(16); return "#"+r+g+b; } // 노드 프로퍼티의 일부를 출력 function outputNodeProps (nd) { var strNode = "Node Type: " + nd.nodeType; strNode = "\nNode Name: " + nd.nodeName; strNode = "\nNode Value: " + nd.nodeValue; // style이 설정된 경우에만 아래를 수행 if (nd.style) { var clr = randomColor(); nd.style.backgroundColor=clr; strNode += "\nbackgroundColor: " + clr; } // 해당 노드의 프로퍼티 출력 alert(strNode); // 현 노드의 자식 노드를 처리한다 var children = nd.childNods; for (var i = children.length - 1; i >= 0; i--) { outputNodeProps(children(i]) } } </script> </head> <body onload="outputNodeProps(document)"> <div id='divId'> <h1>Slipp Study - DOM study</h1> <p>문서 트리를 더 잘 이해하기 위해서 head, body, title, div 엘리먼트로 이루어지 웹페이지를 가정해보자. 이 예에서 div내에는 헤더(h1)와 두개의 문단(p)가 존재한다. 첫 번째 문단에는 <i>이첼릭체</i> 부분도 포함되어 있으며, 두 번째 문단에는 그림(이미지)도 포함되어 있다. 아주 일발적인 웹페이지라 할 수 있다.</p> <p>이미지가 있는 두 번째 문단<img src='dom_tree.png' alt='dom tree' /></p> <p><strong>Hello</strong> how are you doing?</p> </div> </body> </html>
노드 타입
nodeType 명 nodeType 숫자값 ELEMENT_NODE 1 ATTRIBUTE_NODE 2 TEXT_NODE 3 CDATA_SECTION_NODE 4 ENTITY_REFERENCE_NODE 5 ENTITY_NODE 6 PROCESSING_INSTRUCTION_CODE 7 COMMENT_NODE 8 DOCUMENT_NODE 9 DOCUMENT_TYPE_NODE 10 DOCUMENT_FRAGMENT_NODE 11 NOTATION_NODE 12
DOM Core document 객체
- document 객체는 웹페이지 문서에 대한 Core 인터페이스
- document 객체는 페이지 엘리먼트를 생성 / 제거하는 메서드를 제공
- 엘리먼트에 접근하는데 널리 이용되는 getElementById와 getElementByTagName 메서드 제공
- getElementByTagName 메서드는 노드 리스트(nodeLists)를 반환
컨텍스트 내에서 엘리먼트 접근하기
- Element는 DOM Core에서 중요한 요소
- 문서 내의 모든 객체는 Element의 기본 기능과 프로퍼티를 상속받음
- 대부분은 속성을 알아내고 설정하는 것
- 속성의 존재 여부를 알아내는 것들
메서드 getAttribute(name) setAttribute(name, value) removeAttribute(name) getAttributeNode(name) setAttributeNode(attr) removeAttributeNode(attr) hasAttribute(name)
트리 변경
- document는 모든 페이지 엘리먼트의 소유자이자 부모
- 새로운 엘리먼트의 인스턴스를 생성하는 대부분의 팩토리 메서드는 Core document 객체의 메서드
document 객체의 팩토리 메서드
메서드 생성된 객체 설명 createElement(tagname) Element 특정 태그에 해당하는 엘리먼트 생성 createDocumentFragment DocumentFragment document 트리의 특정 부분을 추출할 때 사용하는 document createTextNode(data) Text 페이지 내의 텍스트 createComment(data) Comment XML주석 createCDATASection(data) CDATASection CDATA 부분 createProcessingInstructions(target,data) ProcessingInstruction XML 처리 지시 사항 createAttribute(name) Attr 엘리먼트 속성 createEntityReference(name) EntityReference 나중에 추가될 엘리먼트에 대한 공간 확보 createElementNS(namespaceURI,qualifiedName) Element Element에 대한 네임스페이스 createAttributeNS(namespaceURI,qualifiedName) Attr Element 속성에 대한 네임스페이스
var divList = document.getElementsByTagName("div"); divList; var div = divList[0]; div; var h1 = document.getElementsByTagName("h1")[0]; h1; div.removeChild(h1);
- Node 변경 메서드
메서드 설명 insertBefore(newChild, refChild) 현재 노드 앞에 새 노드를 추가 replaceChild(newChild, oldChild) 현재 노드를 대체 removeChild(oldChild) 현재 노드의 자식을 제거 appendChild(newChild) 문서에 자식 노드를 추가 위의 메서드가 유효하려면 컨텍스트 내에서 사용
- 예
var div = document.getElementById("divID"); var h1 = document.getElementEyId("h1ID"); div.removeChile(h1); ... <div id="divID"> <h1 id="h1ID">Header</h1> </div
이벤트 객체 event object
- 모든 이벤트 핸들러 함수 내부에서 제공되거나 사용 가능한 객체
- 인터넷 익스플로러는 이 외의 브라우저와 이벤트 객체를 다루는 방법 다름
- W3C 호환 브라우저에서는 이벤트처리기 함수에 매개변수 하나 제공
- 이 매개변수가 이벤트 객체
일반 프로퍼티
- 이벤트 종류에 상관없이 일단 이벤트가 캡처되면 여러 종류의 프로퍼티에 존재
- 캡처된 이벤트 자체에 직접 연관
- 특정 이벤트 종류에 종속적이지 않음
type
- 현재 구동되고 있는 이벤트의 이름
- click
- mounseover
- 등
- 이 프로퍼티는 일반적인 이벤트 처리기 함수를 제공하기 위한 목적으로 사용
- 일반적인 이벤트 처리기 함수에서는 선별적으로 관련된 함수를 실행
// 이벤트 타입에 따라 이벤트 핸들러가 다른 효과르 가져오게 하는 예 // 변수를 선언 var googleBG = document.getElementById('viewport'); // 이벤트 연결 // mouseover와 mouseout 이벤트에 같은 함수를 연결 googleBG.onmouseover = googleBG.onmouseout = function(e) { // 이벤트 객체를 정규화 e = e || window.event; // 발생한 마우스 이벤트의 종류에 따라 // 배경색을 전환한다 this.style.background = e.type == "mouseover" ? '#EEE' : '#FFF'; }; // // --------------------- // // google 접속 // www.google.com //
target / srcElement
- 이 프로퍼티는 이벤트를 구동시킨 엘리먼트에 대한 참조를 담고 있음
- srcElement는 인터넷 익스플로러에서 작동
// 문서에 더블 클릭 리스너를 연결 document.ondblclick = function(e) { // 이벤트 객체를 정규화 e = e || window.event; // 올바른 targer노드를 찾는다 var t = e.target || e.srcElement; // 해당 노드를 DOM에서 제거한다 t.parentNode.removeChild(t); };
stopPropagation() / cancelBubble
- stopPropagation() 메서드는 이벤트 버블(또는 캡처) 단계를 중단시킴으로써 현재 엘리먼트가 특정 이벤트를 수신하는 마지막 엘리먼트가 되게 만듬
- cancelBubble 프로퍼티는 인터넷 익스플로러에서 사용 가능
- cancelBubble을 true로 설정하면 stopPropagation() 과 동등
// 이벤트 버블링 정지 function stopBubble (e) { // 이벤트 객체가 제공되었다면, IE 아님 if (e) { // W3C stopPropagation() 메서드 지원 e.stopPropagation(); } else{ // 인너텟 익스플로러 방식 사용 window.event.cancelBubble = true; }; } // 이벤트 연결 element.onclick = funciont(e) { return stopDefault(e); }
preventDefalut / returnValue = false
- returnValue 프로퍼티르 false로 설정하면 브라우저의 기본 동작이 일어나지 않음
- preventDefalut()메서드를 호출하면 모든 W3C호환 최신 브라우저에서 브라우저의 기본 동작이 일어나지 않음
var a = "Click"; document.write(a.link('http://www.google.com')); var l = document.getElementsByTagName('a'); l; l[0].onclick = function(e) { document.title = this.href; preventDefault(); return false; } // 브라우저의 기본 동작이 발생하는 것을 막는 일반 함수 function stopDefault(e) { // 브라우저의 기본 동작을 막는다(W3C) if ( e && e.preventDefalut ) { e.preventDefault(); } else { // IE 브라우저의 동작을 중지시키는 방법 window.event.returnValue = false; } return false; } // a link의 브라우저의 기능을 막음 var a = document.getElementsByTagName('a'); for(var i = 0, max = a.length; i < max; i++) { a[i].onclick = function(e) { document.title = this.href; alert(this.href); return stopDefault(e); } }
마우스 프로퍼티
- 마우스 관련 이벤트
- click, mousedown, mouseup, mouseover, mousemove, mouseout
- 마우스 관련 이벤트가 발생 했을 때만 이벤트 객체 내에서 마우스 프로퍼티들을 볼 수 있음
- clientX / clientY
- 브라우저 창에 대한 마우스 커서의 x, y 상대 좌표
- pageX, pageY
- 렌더링된 문서에 대한 마우스 커서의 x, y 상대 좌표
- 문서를 아래로 스크롤 한 경우, 이 프로퍼티들의 숫자값은 clientX / clientY 프로퍼티의 값과 같지 않음
- 인터넷 익스플로러에서는 이 프로퍼티들이 작동하지 않음
- layerX / layerY, offsetX / offsetY
- 이벤트가 발생한 target 엘리먼트에 대한 마우스 커서의 x, y 상대 좌표
- layerX / layer Y
- 모질라 기반의 브라우저와 사파리에서 사용 가능
- offsetX / offsetY
- 오페라, 인터넷 익스플로러에서 사용 가능
- button
- 현재 클릭되는 마우스 버튼을 나타내는 숫자 값
- click, mousedown, mouseup 이벤트에서만 사용 가능
클릭 W3C 인터넷 익스플로러 왼쪽 1 0 오른쪽 2 2 가운데 4 1 // document.onclick = function(e) { // 이벤트 객체를 정규화 e = e || window.event; var t = e.target || e.srcElement; // ctrl키가 눌린 채 click 발생 확인 if (e.ctrlKey) { // 클릭된 노드를 제거 t.parentNode.removeChild(t); } }
relatedTarget
- 마우스가 방금 떠난 엘리먼트에 대한 참조가 있음
- mouseover / mouseout 을 사용하면서도 방금 전에 마우스가 어디에 있었는지, 또는 잠시 후 어디로 갈지 알아야 할 경우
- clientX / clientY
키보드 프로퍼티
- keydown, keyup, keypress 등의 키보드 관련 이벤트가 시작될 때만 이벤트 객체안에 키보드 프로퍼티가 존재
- ctrlKey와 shiftKey 프로퍼티의 경우는 예외
- 이 두 프로퍼티들은 마우스 이벤트가 진행되는 동안에도 사용 가능
- 예
- Alt + 클릭 / Ctrl + 클릭 하는 것을 확인하기 위해
- 예
- 이외의 모든 경우에 대해서는 이 프로퍼티에 담긴 값이 존재하지 않거나
- 존재하더라도 신뢰하기 어렵움
- 이 두 프로퍼티들은 마우스 이벤트가 진행되는 동안에도 사용 가능
- ctrlKey
- 키보드의 Ctrl키가 눌렸는지 여부를 표현하는 불리언 값을 반환
- 키보드와 마우스 이벤트 모두 사용 가능
- shiftKey
- 키보드의 shift키가 눌렸는지 여부를 표현하는 불리언 값을 반환
- 키보드와 마우스 이벤트 모두 사용 가능
- keyCode
키 키코드 백스페이스 8 탭 9 엔터 13 스페이스 32 왼쪽 화살표 37 위쪽 화살표 38 오른쪽 화살표 39 아래쪽 화살표 40 0 - 9 48 - 57 A - Z 65 - 90
// click 처리기 연결 document.onclick = function(e) { // 이벤트 객체를 정규화 e = e || window.event; var t = e.target || e.srcElement; // ctrl키가 눌린 채 click 발생 확인 if (e.ctrlKey) { // 클릭된 노드를 제거 alert('컨트롤 키 눌림'); t.parentNode.removeChild(t); } // shift키가 눌린 채 click 발생 확인 if (e.shiftKey) { // 알림 alert('시프트 키 눌림'); t.parentNode.removeChild(t); } }
페이지 이벤트
- 주로 페이지의 로딩과 언로딩 작업을 처리
- 페이지를 방문
- 페이지 나갈 때
load
- 페이지가 불러오기 작업이 완료되면 load 이벤트 발생
beforeunload
- 표준과는 전혀 관계 없지만 널리 지원되는 이벤트
- unload 와 유사하게 동작
- 사용자가 현재 페이지를 떠나려 할 때, 정말로 떠나길 원하는지 묻는 승인 메시지 표시
- 이때 '아니오' 선택시 현재 페이지에 계속 남아 있을 수 있음
- 동적인 웹 애플리케이션에서는 사용자가 저장하지 않은 데이터를 잃지 않도록 조치
error
- 자바스크립트 코드 안에서 에러가 발생하면 언제나 error 이벤트가 발생
resize
- 사용자가 브라우저 창의 크기를 변경할 때 resize 이벤트가 발생
scroll
- 사용자가 브라우저 창 안에서 보고 있던 문서의 위치를 옯길 때 scroll 이벤트가 발생
unload
- 사용자가 현재 페이지를 떠날 때 발생
- 사용자가 링크를 클릭할 때 발생
- 뒤로( back) 버튼을 클릭할 때 발생
- 브라우저 창을 닫는 경우 발생
- unload 이벤트는 기본 작동을 우회하는 기법을 적용할 수 없다
- 대안으로 beforeunload 이벤트 사용
// load window.onload = function() { alert('onload'); }; // beforeunload window.onbeforeunload = function() { // 사용자가 왜 이 페이지를 떠나선 안되는지 설명하는 문자열을 반화 return '아직 저장하지 않았습니다. 나갈까요?'; }; // error - window.onerror = function(message) { alert(message); }; // resize window.onresize = function() { alert('resize'); }; // scroll window.onscroll = function() { alert('scroll'); }; // unload window.onunload = function() { alert('unload'); };
UI 이벤트
- 사용자가 브라우저, 페이지 엘리먼트들과 어떻게 상호작용하는지를 다룸
focus
- 페이지 커서의 현재 위치를 알아내는 데 사용
blur
- 사용자가 포커스를 한 엘리먼트에서 다른 곳으로(링크, 입력 엘리먼트, 또는 메이지 그 자체 등) 이동할 때 blur 이벤트 발생
마우스 이벤트
- 마우스 이벤트는 사용자가 마우스 포인터를 이동하거나 마우스 버튼 중 하나를 클릭할 때 발생
click
- 마우스 좌측 버튼을 눌렀다가 같은 엘리먼트 위에서 마우스 버튼을 다시 떼었을 때 발생
dblclick
- 사용자가 연속적으로 재빨리 클릭을 두 번 할 때 발생
mousedown
- 사용자가 마우스 버튼을 누를 때 발생
mouseup
- 사용자가 눌렀던 마우스 버튼을 뗐을 때 발생
mousemove
- 사용자가 마우스 포인터를 페이지 안에서 최소 한 픽셀 이상 움직였을 때 발생
mouseover
- 사용자가 다른 곳에서 어떤 엘리먼트 위로 마우스를 옮겨 올 때 발생
mouseout
- 엘리먼트 밖으로 마우스를 옮겼갈 때 발생
// document.onmousemove = function(e) { // fixEvent(e); e = e || window.event; console.log('--------------------------------------------'); console.log('clientX : ' + e.clientX + '--' + 'clientY : ' + e.clientY); console.log('pageX : ' + e.pageX + '--' + 'pageY : ' + e.pageY); console.log('layerX : ' + e.layerX + '--' + 'layerY : ' + e.layerY); }; // function fixEvent(e) { // IE if (!e) { e = window.event; e.target = e.srcElement; e.layerX = e.offsetX; e.layerY = e.offsetY; } return e; }
키보드 이벤트
- 텍스트 입력 공간의 내부든 외부든 상관없이, 사용자가 키보드로 키를 입력하는 모든 경우
keydown
- 키가 눌릴 때 가장 먼저 발생
- 만약 사용자가 키를 계속 누르고 있으면 keydown 이벤트가 계속해서 발생
keypress
- 보통 keydown 이벤트와 같은 것으로 간주
- 키 입력의 기본 작동을 우회하고자 할 때, 그 처리는 반드시 keypress 이벤트에서 처리 해야 함
keyup
- keyup 이벤트는 (keydown 이벤트 후에) 마지막으로 발생
// <input> 엘리먼트에서 실수로 엔터키가 입력해 폼을 전송 안되게 함 var input = document.getElementsByTagName("input"); for ( var i = 0; i < input.length; i++ ) { // <input> 엘리먼트에 keypress 이벤트 처리기를 연결 input[i].onkeypress = function(e) { // 엔터키를 입력했을 때 기본 동작이 발생하지 않게 한다 return e.keyCode != 13; }; }
폼 이벤트
- 폼 이벤트는 주로 HTML 폼을 구성하는 주된 요소인 <form>, <input>, <select>, <button>, <textarea> 엘리먼트 등을 다룸
select
- 사용자가 입력 공간 안에서 마우스를 사용해 다른 텍스트 블럭을 선택할 때 발생
change
- 입력 엘리먼트 (<select>, <textarea> 엘리먼트를 포함한) 안의 값을 사용자가 변경했을 때 발생
submit
- 폼안에서 사용자가 폼 안에 위치한 submit 버튼을 클리했을 때,
- 혹은
- 폼안의 어떤 입력 엘리먼트에서 엔터키나 Return키를 입력했을 때 발생
- 사용자가 submit 처리기를 연결하고 submit 버튼에 click 처리기를 부착하지 않으면
- 사용자가 폼을 제출하려는 모든 시도를 감시할 수 있음
reset
- 사용자가 폼 안의 reset 버튼을 클릭했을 때만 발생
// 페이지 안에서 첫 번째 <textarea>를 찾는다 var textarea = document.getElementsByTagName("textarea")[0]; // select 이벤트 리스너를 연결 textarea.onselect = function() { // 텍스트 선택 작업을 할 수 없게 한다 return false; }; // submit // 페이지 안에서 첫 번째 폼에 submit 처리기를 연결 document.getElementsByTagName("form")[0].onsubmit = function(e) { // 사용자가 입력한 이름을 가져옴 var name = ducument.getElementById('name').value; // <h1> 엘리먼트의 값을 Hello Name! 으로 설정 // 여기서 Name은 사용자가 폼에 입력한 이름 값 document.getElementsByTagName('hi')[0].innerHTML = "Hello " + name + '!'; // 폼이 서버로 전송되지 않도록 한다 return false; };
그 외
- 클로저 Closure
- prototype chain ???
- 디버깅과 테스트
- 디버깅
- 에러 콘솔
- 인터넷 익스플로러
- 파이어폭스
- 사파리
- 크롬
- 오페라
- 에러 콘솔
- 테스트
- JSUnit
- 디버깅
기억할 것
- Array 객체
- closure 클로저
- callback 콜백함수
- arguments 매개변수
- method channing 메소드 체이닝
- 변수 범위
- 호이스팅 hoisting
- BOM
- DOM
- ...
A 기타
A.1 자바스크립트 참고 자료
- 자바스크립트 웹 2.0 O'Relly 한빛미디어
- 프로 자바스크립트 테크닉 인사이트
- begging JavaScript 4ed Wrox
- professinal JavaScript Wrox
- Head First JavaScript O'Relly 한빛미디어
- 모던웹을 위한 HTML5프로그래밍 한빛미디어
- professinal JavaScript for webdevelopers Wrox
- 모던웹을 위한 JavaScript jQuery입문 한빛미디어
- 자바스크립트 클로저
- Ext JS 4 Web Application Development Cookbook packt
- Ajax prototype.js 프로토타입 완전분석 위키북스
Prototype and script.aculo.us pragmatic
- 브라우저 이벤트 참고
- DOM 레벨 1 : http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html
- HTML DOM 레벨 1: http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html
- DOM 레벨 2 : http://www.w3.org/TR/DOM-Level-2-Core
- HTML DOM 레벨 2: http://www.w3.org/TR/DOM-Level-2-HTML
- Core API에 대한 레벨 2 Script Binding: http://www.w3.org/TR/2003/REC-DOM-Level-2-HTML-20030109/ecma-script-binding.html
XML for Scrip :http://xmljs.sf.net
Google AJAXSLT :http://goog-ajaxslt.sf.net/
- DOM Core API에 대한 ECMAScirpt Binding: http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html
- DOM 메서드 및 모든 최신 브라우저에 대한 처리 결과 비교
- CSS1 selector :http://www.w3.org/TR/REC-CSS1#basic-concepts/
- CSS2 selector :http://www.w3.org/TR/REC-CSS2/selector.html
- CSS3 selector :http://www.w3.org/TR/2005/WD-css3-selectors-20051215/
- DOM-LEVEL-3-CORE : http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/
B 자바스크립트에서 알고 싶은 내용
- 여기에 궁금한 것들을 적어 주세요.
예외 핸들링콜백 등록 방법
B.1 backbone.js를 학습하며 필요하다고 생각한 내용
- javascript extend => var Shape = Backbone.Model.extend({
- javascript event - event bind, event listener