1장 : 자바스크립트란 무었인가
ECMAScript
ECMA스크립트(ECMAScript, ES[1])는 Ecma 인터내셔널의 ECMA-262 기술 규격에 정의된 표준화된 스크립트 프로그래밍 언어이다.
이 언어는 웹 상에서 널리 쓰이며, 흔히 자바스크립트 또는 J스크립트로도 생각할 수 있지만 두 용어는 특별한 의미 차이가 있다.
ECMA스크립트와 자바스크립트, J스크립트의 관계를 이해하기 위해서는 ECMA스크립트의 역사를 알아야 한다.
ECMASCript? ES?
브라우저 전쟁 시절 개발자들은 몸살을 앓았다.
넷 스케이프 사의 자바스크립트가 부러웠는지 사용자 층을 더 끌어내기 위해 MS의 IE 3에도 JScript라는 이름으로 자바스크립트를 탑재하였다.
하지만 둘의 내용이 매우 달랐는지, 같은 기능을 구현하기 위해 개발자가 해야하는 일들이 더 많아졌다.
날이 가면 갈 수록 사용자를 끌어내기 위해 서로 기능을 넣다보니 Javascript와 JScript는 날이 가면 갈 수록 달라지는 경향을 보였다.
이에 대한 심각성을 파악하고, European Computer Manufacturers Association(ECMA, 현 ECMA International)에서는
이러한 자바스크립트에 대한 표준을 내리게 된다.
또한 ECMA에서는 자바스크립트의 표준만 내리는 게 아니라 다른 표준안도 정하기 때문에 그와 구분하기 위해 숫자를 붙였는데 262다.
ECMA262라고 보인다면 아, 자바스크립트 표준 규격이구나라고 생각하면 될 것 같다.
자바스크립트는 언어이고, ES는 스펙이다.
IE8에서는 ES3 스펙을 준수한 거고, IE9에서는 ES5 스펙을 준수한 거다.
2장 : HTML속의 자바스크립트
BOM & DOM
BOM은 'Broser Object Model(브라우저 객체 모델)'의 약자이며 브라우저의 정보나 URL 정보, 모니터 화면 정보 등을 취득하거나 제어할 수 있는 객체라고 생각하면 되고 브라우저 객체의 최상위 객체는 window 객체이다.
DOM은 'Document Object Model(문서 객체 모델)'의 약자이며 BOM과 달리 표준화가 되어 있다. 이는 HTML 요소를 제어(생성, 삭제)하기 위해 사용되며 이러한 요소를 제어하는 자바스크립트를 좀 더 쉽게 제어할 수 있도록 만들어 진 것이 jQuery 이다.
script 태그의 async와 defer 속성
script가 문서를 직접 만지고 조작하거나 서로 간 로딩 순서가 중요할 때에는 defer 속성을 쓰고, 그렇지 않다면 async 속성을 써서 웹 페이지 로딩 속도를 줄일 수 있다.
DOCTYPE(문서형 정의) 선언
문서형 정의(DTD:Document Type Definition)xx은 HTML5, XHTML, HTML의 세가지 문서 유형이 존재하며, 기술한 유형에 따라 마크업 문서의 요소와 속성등을 처리하는 기준이 되며 유효성 검사에 이용된다.
What is "!Doctype"?
The document type tells Web browsers and other user agents which version of HTML you have used so that they know how to render your pages.
<noscript>
HTML <noscript>
요소는 페이지에 있는 스크립트 타입이 지원되지 않거나, 브라우저에서 스크립팅이 꺼져있는 경우에 삽입될 html 구획을 정의합니다.
3장 : 언어의 기초
ECMAScript 5의 'Strict Mode'
Strict Mode는 ECMAScript 5에 추가된 모드로 ECMAScript 3와 호환성 때문에 존재하지만 ECMAScript 5에서는 폐기된 기능들은 사용하지 못하도록 하는 모드입니다.
그래서 Strict Mode를 사용하면 안전하지 않은 동작을 수행했을 때 차단되거나 예외가 발생해서 더 안전한 스크립트를 작성할 수 있도록 도와줍니다.
var, let, const 차이점은?
Function Declarations(함수선언) vs Function Expressions(함수표현)
정의하지 않은 변수에 실행할 수 있는 유의미한 조작은 typeof
뿐.
undefined는 null에서 파생했으므로 둘 비교는 true
console.log(null == undefined);
사칙연산에 있어서 소수점 아래 17자리까지는 정확하지만... 0.1 + 0.2 = 0.30000000000000004
Not a Number
에러로 취급하지 않음.
NaN이 떨어져도 그 뒤로 계속 스크립트 수행함.
심지어 NaN == NaN은 false임 어느거와도 같지 않음.
때문에 isNaN이 존재.
Object.prototype.isPrototypeOf()
isPrototypeOf() 메소드는 해당 객체가 다른 객체의 프로토타입 체인에 속한 객체인지 확인하기 위해 사용됩니다.
instanceof vs. isPrototypeOf()
The main difference between instanceof and isPrototypeOf is that instanceof can make a check for an object that has no constructor.
But when you do have a constructor function, instanceof is cleaner and usually preferred(because of its history with Java, I believe)
Object.prototype.hasOwnProperty()
hasOwnProperty() 메소드는 객체가 특정 프로퍼티를 가지고 있는지를 나타내는 불리언 값을 반환한다. obj.hasOwnProperty(prop)
모든 객체는 hasOwnProperty 를 상속하는 Object의 자식이다. 이 메소드는 객체가 특정 프로퍼티를 자기만의 직접적인 프로퍼티로서 소유하고 있는지를 판단하는데 사용된다. in 연산과는 다르게, 이 메소드는 객체의 프로토타입 체인을 확인하지는 않는다.
o = new Object();
o.prop = 'exists';
o.hasOwnProperty('prop'); // returns true
o.hasOwnProperty('toString'); // returns false
o.hasOwnProperty('hasOwnProperty'); // returns false
[속깊은 자바스크립트 강좌] 객체지향의 기본: prototype
동일과 비동일
ECMAScript에서 두 연 산자 모두 피연산자를 비교하기 전에 변환. 이러한 변환을 타입강제라 부른다.
- 피연산자가 불리언이면 숫자로 변환 false:0, true:1
- 피연산자가 문자고 다른 하나는 숫자라면 문자를 숫자로 바꾸는 시도함
- 하나는 객체 하나는 객체가 아니라면 객체의 valueOf의 원시값으로 비교
- null과 undefined는 동일
- 하나가 NaN고 동일 연산자는 false라면 true리턴
- NaN과 NaN은 같지 않음
- 두 피연산자가 객체라면 메모리 주소로 비교
arguments
arguments 객체의 프로퍼티 값을 바꾸면 이에 대응하는 매개변수에 자동으로 반영하는점 단방향으로
function doAdd(num1, num2){
arguments[1] = 10;
console.log(num1, num2);
console.log(arguments);
}
doAdd(10); //10, undefined
doAdd(10,30); //10, 30
4장 : 변수와 스코프, 메모리
실행 컨텍스트 execution context
- 변수낭 함수의 실행 컨텍스트는 다른데이터에 접근할 수 있는지, 어떻게 행동하는지 규정함.
- 가장 밖의 실행 컨텍스트는 전역 컨텍스트임 웹브라우저에 보면 window 변수
- 함수를 실행하면 독자적인 컨텍스트가 형성됨
- 코드 실행이 함수로 들어갈때마다 스택에 쌓임
스코프 체인 scope chain
- 컨텍스트 코드실행하면 변수객체에 스코프 체인이 만들어짐
- 스코프 체인의 목적은 실행 컨텍스트가 접근할 수 있는 모든 변수와 함수에 순서를 정의
eval
자스에는 블록 레벨 스코프가 없음
if(true){
var color = 'color';
}
alert(color); //color
5장 : 참조타입
배열감지
instanceof
의 문제점
메인에서 Array생성된 var aaa를 iFrame으로 전송한다음
aaa instanceof Array라고 햇을때!
이 Array는 iFrame의 Array로 aaa가 상속받는 메인 Array가 아니므로 false리턴함.
해결하기 위해 Array.isArray() 제공함.
toLoacleString toLocalString toString different
이것들은 브라우저 특성타서 디버깅에는 유용하지만 코드로 쓰면 안됨.
.push(), .pop(), unshift(), shift() - 배열에 원소 추가/제거 하기
배열에 원소를 추가하는 메서드에는 .push()와 .unshift()가 있습니다.
.push()는 배열의 맨 끝에, .unshift()는 배열의 맨 앞에 원소를 추가합니다.
배열에서 원소를 제거하는 메서드에는 .pop()과 .shift()가 있습니다.
.pop()은 마지막 원소를, .shift()는 맨 앞의 원소를 제거합니다.
함수선언 vs 함수표현식
스크립트 엔진이 실행 컨텍스트에 데이터를 불러올 때 중요한 차이가 있음.
함수 표현식은 코드 실행이 해당 줄까지 진행하기 전에는 사용할 수 없음.
함수 프로퍼티
모든 함수에 공통인 프로퍼티는 length, prototype
function sayName(first, second){}
console.log(sayName.length); //2
프로토타입 (Prototype)
call apply bind 차이
funcSample.apply(this, arguments);
funcSample.apply(this, [1,2,3,4]);
funcSample.call(this, 1,4,2,3);
apply와 call의 차이점은 매개변수를 어떻게 넘겨주나 차이뿐.
apply와 call의 진가는 매배견수를 넘기는게 아니라 this를 바꾸는것임.
bind는 ie9이상에서 됨
decodeURI decodeURIComponent
encodeURIComponent()
- 입력을 URL로 인코딩 된 문자열로 변환합니다.
encodeURI()
- 입력을 URL 인코딩하지만 전체 URL이 주어진 것으로 가정하므로 프로토콜 (예 : http : // ) 및 호스트 이름 (예 : www..com )을 인코딩하지 않아 유효한 URL을 반환합니다.
6장 : 객체 지향 프로그래밍
프로퍼티 타입
데이터 프로퍼티
- configurable : delete를 통한 삭제, 속셩변경, 접근자로 변경 할수 있음을 나타냄
- enumerable : for in loop에서 해당 프로퍼티를 반환함을 나타냄.
- writable : 프로퍼티 값을 변경할 수 있음을 나타냄
- value : 프로퍼티의 실제 데이터 값을 포함.
var person = {}; Object.defineProperty(person, 'name', { writeable: false, value: 'name', configuralbe : false )};
접근자 프로퍼티
- configuralbe : 위와 동일
- enumerable : 위와동일
- get
- set
var book = { _year: 2004, edition: 1 } Object.defineProperty ... Object.defineProperties ...
Person.prototype.isPrototypeOf('namd')
호출하는 프로토타입으로 인스턴스가 만들어졌는지 확인
object.hasOwnProperty
인스턴스에 프로퍼티가 있는지 확인
name in object
오브젝트에 name 프로퍼티가 존재하는지 확인
Object.keys
object 객체의 key값을 배열로 리턴
향상된 생성자 패턴
function Person(){};
Person.prototype = {
constructor: Person,//prototype에 객체로 초기화 하므로 생성자 지정을 해야 construct가 Person으로 표시됨.
name : 'zsgg',
age : 21
}
프로토타입 동적성질
var friend = new Person();
Person.prototype.say = function(){};
friend.say();// ok
function Person(){};
var friend = new Person();
Person.prototype = {
say : function(){}
};
friend.say();// **error**
prototype 포인터는 생성자가 호출될 때 할당됨.
다른 객체로 바꾸면 생성자와 원래 프로토타입 사이의 연결이 끊어짐.
인스턴스는 프로토타입을 가리키는 포인터를 가질 뿐 생성자와 연결된 것이 아님.
생성자의 프로토아입을 바꾸면 그 이후에 생성한 인스턴스는 새로운 프로토타입을 참조하지만, 그 이전에 생성ㅎ나 인스턴스는 바꾸기 전의 프로토아입을 참조함.
프로토타입 단점
진짜 문제는 프로퍼티가 참조 값을 포함한 경우.
function Test(){
this.argArray = ['arg array'];
}
Test.prototype.argProtoArray = ['proto array'];
var person1 = new Test();
var person2 = new Test();
person1.argArray.push('after push');
person1.argProtoArray.push('after push');
console.log(person1.argArray);// Array [ "arg array", "after push" ]
console.log(person2.argArray);// Array [ "arg array" ]
console.log(person1.argProtoArray);// Array [ "proto array", "after push" ]
argProtoArray는 프로토타입의 객체이므로 변경시 모든 인스턴스의 argProtoArray가 가리키는 값이 변경됨.
프로토타입 체인의 단점
function Test(){
this.argArray = ['arg array'];
}
function TestSub(){};
TestSub.prototype = new Test();
var instance1 = new TestSub();
var instance2 = new TestSub();
instance1.argArray.push('push by instance');
console.log(instance1.argArray);// Array [ "arg array", "push by instance" ]
console.log(instance2.argArray);// Array [ "arg array", "push by instance" ]
프로토타입으로 상속을 구현하면 프로토타입이 다른 타입의 인스턴스가 되므로 처음에 인스턴스 프로퍼티였던 것들이 프로토타입 프로포티로 바뀜.
결국, 상위 객체의 프로퍼티들이 하위에 프로토타입 프로퍼티로 들어가게됨. 그러면 argArray가 argProtoArray처럼 동작함.
생성자 훔치기
function SuperType(){}
function SubType(){
SuperType.call(this);
/*
call을 함으로써
SuperType function 내 var 선언들을 SubType에 정의할수 있음.
SuperType.call(this, arg1, arg2 ~) 처럼 SuperType이 파람을 가지고있을때는 값전달도 가능.
*/
}
프로토타입 참조값에 얽힌 상속문제 해결하기 위해사용되었음.
기본 아이디어는 매우단순, 하위 타입 생성자안에서 상위 타입 생성자를 호출
생성자 훔치기 단점
메서드를 생성자 내부에서만 정의해야해서 함수 재사용이 불가능
게다가 상위 프로토타입에 정의된 메서드는 하위 타입에서 접근할 수 없는 문제도 있음.
조합상속
function SuperType(){}
function SubType(){
SuperType.call(this);
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType
7장 : 함수 표현식
스코프 체인이란 변수 객체를 가리키는 포인터 목록이며 객체를 직접 포함하는 것은 아님
this 객체
this 객체는 런타임에서 함수가 실행중인 컨텍스트에 묶임.
익명함수는 특정 객체에 묶여있지 않으므로 스트릭트 모드가 아니라면 this객체는 window임.
자바스크립트 클로저 쉽게 이해하기
클로저는 외부함수(포함하고 있는)의 변수에 접근할 수 있는 내부 함수를 일컫습니다.
즉시실행함수에는 왜 감싸는 괄호가 들어갈까?
즉, “함수문에는 이름이 필요함”이라는 메세지는 자바스크립트 엔진이 이름이 없다고 해서 그냥 expression 으로 해석하는게 아니라는 것을 뜻한다.
이제 원인은 모두 파악이 되었다. 그렇다면 소괄호가 하는 역할은 무엇일까? 앞서 함수문이 함수식이 되기 위해서 필요한 것은 연산자라고 말한 바 있다. 한글자만으로 기능하는 연산자도 많이 있지만 그룹화 연산자는 피연산되는 함수의 리턴값에 아무 영향을 주지 않으면서, 함수의 경계를 개발자가 파악하기 쉽게 만들어준다.
ETC
JavaScript로 만나는 세상
'Learning' 카테고리의 다른 글
REST API 디자인 규칙 (1) | 2018.07.20 |
---|---|
프로젝트가 서쪽으로 간 까닭 (0) | 2018.07.10 |
네이버를 만든 기술 - 자바 편 (0) | 2018.07.10 |
Java 8 in Action (0) | 2018.06.11 |
HTTP 완벽가이드 (0) | 2018.04.28 |
댓글