본문 바로가기

IT/JavaScript

20160623 [JavaScript]


Front-end
Back-end
Web-appJava+Alpha
AWS(Amazon Web Service)
Asure
서비스
데이터 분석

Polyglot : 다양한 언어를 사용하는 사람

스크립트 : 특정 환경에서 동작하는 것
Javascript Java의 인기에 편승하려고 이름지음
Script language  c+로 올려도 java로 봐야됨

Interpreter 방식 Python Code와 Data가 구분되지 않음
REPL(Read, Evaluate, Print, Loop)

자바스크립트가 독특한 이유?
두번 읽는다 
<Script>가 </body>위에 올리면 화면이 열린 상태에서 script실행

코딩 스타일
캐싱처리 : 한번 받으면 갱신되기 전까지 캐시되어 있음

200 - Ok
300 -  애러 캐시 에러
400 - 404 URL 에러
500 - 내부 서버 에러

ESMAScript 스크립트라면 요구하는 것 javascript, actionscript
5버전까지 나옴, 최근은 6까지 나옴 class 구현가능

[JavaScript] ECMAScript 5

HTML5와 함께 출현한 자바스크립트 표준안을 ECMAScript 5 라고 부릅니다. ECMAScript 5는 기존의 자바스크립트에서 특히 객체 관련 부분을 많이 보완했습니다. 참고로 ECMAScript 5는 인터넷 익스플로러 9이상이나 그 외 브라우저에서만 작동합니다.


자바스크립트에서 strict mode를 사용해야 하는 이유

http://blog.aliencube.org/ko/2014/01/02/reasons-behind-using-strict-mode-while-coding-javascript/

use strict 쓰고 시작

var 키워드, 연산자

자바스크립트는 두번 읽는다.
1. 해석 선언
2. 실행 연산
undefined 초기화 되지 않음
not defined 변수 자체가 없음

{}는 메모리공간 statement 구조를 해석 

var는 변수의 context를 정하는 것!!!

var를 명시하지 않으면 전역
undefine 구조는 만들었지만, Reference가 되지 않음
undefine 변수가 선언만 되고, 초기화 된 적이 없는 상황

모든 자바스크립트는 참조타입 <-> 원시타입 or 데이터타입
var value = 10
value.toString 이게 됨 (자바에서 Int(데이터타입) Integer(참조타입)

동적인것> 정적인것.

TypeScript
MS에 의해 만들어졌으며, 자바스크립트를 대체하기보다는 부족한점을 보완하여 편리성, 확장성, 생산성 향상을 도모한 어플리케이션 규모의 개발 프로젝트입니다.
http://mydreamisthebestcooder.tistory.com/46

객체 리터럴 : var obj ={key:값, key:값};
js는 타입이 유연함? typescript

function 함수이름(파라미터...(매개변수)){ }
리턴타입 없음
파라미터 갯수에 영향을 받지 않음(자바에서 오버로딩이 없음)


1개만 넣으면 2번째꺼가 undefined 됨

스코프, context, life

함수의 매개변수
- arguments 불변의 배열


실행 컨텍스트와 스코프
- 전역 컨텍스트 : var 없이 선언될 때
- 실행 컨텍스트
- 컨텍스트 스택 : doA->doB->doC
- 컨텍스트에서 코드를 실행하면 '스코프 체인scope chain'이 생성



javascript 기초 - Scope, Scope Chain & arguments

http://insanehong.kr/post/javascript-scope/


소개

이전글에서 소개한 function에 대한 글의 연속으로 이번글에서는 function 이 가진 여러가지 특성들에 대하여 알아보려고 한다. 이번 글에서 소개하는 function 의 특성은 ScopeScope Chain 그리고 arguments 객체 이다. 이들은 Execution Context라는 개념에서 함수객체가 만들어지면서 생성되는 것들로서 이글 이후에 소개될 Execution Context에 대한 이해를 위해 필요로하는 녀석들이다. 그러므로 이번글에서 소개되는 내용을 통해 ScopeScope Chainarguments 에 대한 기본적인 이해에 도움이 되었으면 한다.

함수(function)의 특징

함수는 전역변수와 지역변수를 활용할 수 있다.

함수는 자신의 statement 안에서 변수를 선언하여 지역변수로 사용할 수 있다.

이때 선언된 지역변수는 해당 함수안에서만 접근가능한 private variable 이 된다. 즉 함수 코드블럭을 벗어나게 되면 해당 변수는 메모리에서 사라지게 된다.

function foo() {
   var x= 1; // 함수안에서 선언된 변수임에 지역변수이다. 
   return x;
}
console.log(foo());
> 1
console.log(x); // 외부에서 참조할수 없다.
>undefined

하지만 global 영역에 선언된 전역변수는 자바스크립트 코드 어디에서든 사용할 수 있기에 *함수안에서도 전역변수를 이용할 수 있다 *

var x= 1; // global 영역에 선언된 전역변수

function foo() {
   return x; // 전역변수 x를 return
}
console.log(foo());
> 1
console.log(x); // 어디서든 참조가능한 전역변수
> 1

함수에서 전역변수와 지역변수사용함에 있어 재미있는 현상이 하나 있다. 바로 중첩된 이름의 변수 사용이다. 자바스크립트는 global 영역에 선언된 변수와 동일한 이름의 지역변수를 사용할수 있다. 이로 인해 디버깅 과정중에 많은 혼란을 초래하기도 한다.

var x='hello'; // 전역변수 x 에 hello 할당.

function foo() {
   var x='world';  // 지역변수 x 에 world할당.
   return x;  
}

console.log(foo());
>world // 함수실행에 따라 지역변수 x에 할당된 world 가 출력된다.
console.log(x);
>hello // 전역변수 x에 할당된 hello 가 출력된다.

전역변수와 지역변수를 동일한 이름으로 사용했을경우 지역변수에서 다른 값을 할당하여도 전역변수에는 아무런 변화가 없다.

즉 전역변수와 지역변수를 동일한 이름으로 사용하여도 각각 다른 변수객체가 만들어진다는 것을 알수 있다. 이 현상에 대해 정확히 이해하기 위해서는 Scope 와 Scope Chain 이란 녀석들에 대해 이해하고 있어야 한다.

함수객체의 Scope & Scope Chain

Scope & Scope Chain

ECMA-262 3 Edition 에서는 함수객체는 [[scope]] 라는 프로퍼티를 가지며 [[scope]]는 함수객체가 생성되는 시점과 관련된 Object Reference 정보를 가지고 있으며 이 Object Reference 정보들을 Scope Chain 이라고 한다고 정의한다. 즉 scope는 함수객체가 접근가능한 Valiable Object의 유효범위이며 이 Valiable Object들의 집함을 Scope Chain 이라고 한다.

함수객체는 생성과정에서 함수구문 내에서 선언된 지역변수들을 Valiable Object 라는 객체에 저장한다. 그리고 전역객체(Global Object)의 Valiable Object 와 연결된다. 전역객체의 Valiable Object는 전역객체 자신이다. 이때 이 Valiable Object들에 대한 연결들을 Scope Chain 으로 관리하고 [[scope]]를 통해 Scope Chain을 참조하여 함수객체가 가지는 유효범위를 설정하게 되는 것이다.

var x = 1;
function foo() {
    var y = 10;
    return a+x;
}
console.log(z);
>ReferenceError;

위 예제코드의 foo() 함수객체가 생성될 때의 [[Scope]]와 Scope Chain 에 대한 연결은 아래 다이어그램을 보면 쉽게 이해할수 있다.

다이어그램1

변수의 검색은 이 Scope Chain 에서만 탐색 된다. **Scope Chain의 하위에서부터 상위로 등록된 변수가 있는지 찾아가며 가장 처음 탐색되는 scope에 등록된 변수를 이용*한다. 즉 *Scope Chain 에의해 탐색되지 않는 변수는 undefined **이며 그런 이유로 예제의 console.log(z); 는 foo함수가 가진 유효범위에서 찾을 수 없는 변수 z 에 대한 접근을 하기 때문에 ReferenceError 가 되는 것이다. 처음의 의문으로 돌아가서 전역변수 x와 지역변수 x가 동일한 이름으로 사용이 가능한 이유는 이처럼 각각 x에 접근하기 위해 참조하는 Valiable Object가 다르기 때문인 것이다.

3. 변수선언에 사용되는 var 키워드

자바스크립트에서 변수선언은 반드시 var 키워드를 사용하여야 한다는 착각을 하고 있는 입문자들 여럿보았다. 하지만 이는 잘못된 생각이다. var 키워드의 사용은 해당 변수의 scope를 설정하는 역활만을 한다. var 키워드를 사용한 변수선언은 현재 Scope에 등록되며 var 없는 변수 선언은 Global Scopet에 등록되는 것이다. 이런 이유로 함수안에서 var 없는 변수를 사용하면 함수외부에서도 사용가능 하다.

x=1; //전역변수로 등록된다. 
function sum() {
   y=2; //전역변수로 등록된다. 
   var z = 3; //var 키워드 사용으로 현재 scope에 등록된다. 
   return x+y+z;
}
console.log(sum());
> 6
console.log(x+y);
> 3 //x,y 는 전역변수로 등록되기 때문에 정상 수행된다. 
console.log(x+y+z);
> ReferenceError // z는 함수실행이 종료되면 메모리에서 비워진다.

위 예제를 보면 알수 있듯이 y 변수는 함수내부에 선언되었지만 var 없이 선언 되었기 때문에 전역객체에 등록되는 전역변수가 된다. var 를 사용한 z는 현재 스코프 즉 현재 실행되는 코드 블럭의 주인읜 객체의 Valiable Object 에 등록되기 때문에 함수가 호출되어 실행되고 있는 시점에서의 런타임 주체인 sum 함수의 Valiable Object에 등록되었다가 함수 실행이 종료되면 메모리에서 비워진다.

하지만 이런 코드패턴은 그다지 좋은 방법이 아니다. var 없는 변수는 전역객체에 등록이 됨으로 항시 메모리를 차지하고 있을뿐 아니라 변수에 값이 할당되는 것은 런타임에서 일어나는 일이기에 해당 변수는 함수객체가 생성되기 이전 즉 함수호출되기 이전에는 global scope 에 등록되지 않는다.

x=1; 
function sum() {
   y=2; 
   return x+y;
}
console.log(x+y);
> ReferenceError 

또 한가지 var 없는 변수선언을 지양하는 이유는 복잡하고 길어진 코드내에서 var 없이 사용된 변수는 어디에서 어떻게 바뀌는지 추적하기 힘들기 때문이기도 하다. var 없이 선언된 변수는 함수내에서 수정된 값이 전역 scope에 직접적으로 영향을 끼치게 됨으로 본인도 모르는 사이 엄청난 버그를 양산해 낼수 있기 때문이다.

함수는 0개 이상의 매개변수(parameter)를 가질 수 있다.

매개변수(Parameter) 란?

매개변수란 함수호출시 함수객체로 넘겨질 인자값들을 담기 위해 함수명세에서 선언된 변수들을 뜻한다.

함수는 내부에서 선언된 지역변수와 global 영역에 선언된 전역변수를 사용하는 방법말고 변수를 활용하는 한가지 방법이 더 있다. 바로 함수호출시 인자로 전달받은 값을 저장할 변수를 미리 함수명세에 선언해 두는 것이다.

이런 매개변수는 ,(comma)를 기준으로 기분하여 선언하면 한개 이상의 매개변수도 사용할 수 있으며 해당 함수의 scope에 등록되어 함수내부 어디에서든 별다른 선언없이 함수호출시 넘어온 인자값을 할당받아 바로 사용할 수 있다.

function sum(x,y) {
    return x+y;
}

console.log(sum(1,2));
> 3

console.log(sum(1,2,3));
> 3

console.log(sum(1));
> NaN

console.log(sum());
> undefined

위 예제에서 알수 있듯이 명세에 선언된 매개변수보다 많은 매개변수가 전달될 경우 넘어온 순서대로 매개변수로 할당하고 남은 인자값은 버려진다. 재미있는 사실은 넘어온 값이 매개변수보다 적을 경우에 실행 된다는 것이다. 흔히 함수호출시 선언된 매개변수에 대한 인자를 넘기지 않아 생기는 undefined 를 syntax error 라고 생각한다.

하지만 이는 함수객체 생성과정에서 매개변수로 선언된 변수를 Valiable Object에 추가하면서 기본적으로 undefined 를 할당하며 생긴 결과이지 syntax error 가 아니다.

다이어그램2

이렇게 함수호출시 전달된 인자값들은 함수객체가 가진 arguments 객체에 저장된다.

arguments 객체

arguments 객체

자바스크립트의 모든 함수객체 scope는 arguments 라는 프로퍼티를 가지고 있다. 이 arguments는 Function에 넘겨진 모든 인자에 대한 정보가 담겨 있는 arguments Object 라는 특별한 객체를 가리키고 있다.

정의에서 말했듯이 함수객체의 Valiable Object의 프로퍼티로 추가되는 arguments는 arguments Object를 가리킨다. 이 arguments Object 는 넘어온 인자의 순서에 따른 인덱스를 가진 유사배열객체이다. 유사배열객체라는 것은 매우 중요한 특성이다.

arguments Object에 저장된 인자값들에 대한 접근은 배열과 동일한 [] 를 사용하지만 **arguments Object는 Array Prototype Object를 상속하는 객체가 아니다.**그러므로 arguments Object 객체에는 push()pop()slice()등이 메소드를 가 존재하지 않는다.

function sum(x,y,z) {
   var total =arguments[0] +arguments[1]+arguments[2];
   return total;
}
console.log(sum(1,2,3));
> 6

위 코드의 scope에 대한 다이어그램을 보도록 하자

다이어그램3

다이어그램에서 보면 알수 있듯 arguments Object는 넘어온 인자값을 저장하며** .length와 .callee 라는 프로퍼티를 가지고 있다.**.callee 프로퍼티는 현재 실행되고 있는 function 을 가리키는 프로퍼티 이다. sum() 함수객체의 .length 프로퍼티와 arguments 객체가 가진 .length 프로퍼티는 서로 다른 의미를 갖는다. 함수객체의 .length 는 함수명세에 선언된 매개변수의 수를 arguments 의.length는 함수호출시 넘어온 인자값의 수를 나타내는 프로퍼티들이다. 함수객체와 arguments 객체가 가진 .length 프로퍼티를 이용하면 함수명세에 선언된 매개변수와 동일한 수의 인자값이 넘어왔는지 체크할수 있다.

function checkParameter(x,y,z) {
    if(arguments.length == arguments.callee.length) return true;
    else return false;
}

console.log(checkParameter(1,2,3));
> true 
console.log(checkParameter(1,2));
> false

arguments를 이용하려면 반드시 주의해야하는 사항이 있다. arguments는 함수객체 생성과정에서 만들어지지만 *arguments라는 이름의 변수를 지역변수를 선언하여 사용하면 arguments는 만들어지지 않는다. *

*.callee 라는 프로퍼티는 현재 호출된 function을 가리키는 참조프로퍼티다. 이 프로퍼티는 이름없는 함수에서 재귀를 구현할때 사용하면 참초되는 이름이 없더라도 함수내에서 자기 자신을 재귀호출 할수 있다. *

var total=0;
(function (x) {
    if(x>=0) {
          total+=x;
          x--;
          arguments.callee(x);
    }   
})(10);
console.log(total);
> 55

갈무리

이번글에서 알아본 내용들은 후에 있을 Closure와 Execution Context 에 대한 설명에서 나오는 용어들의 풀이정도라고 생각하면 될것이다.

즉 이번 글에서 해당 용어들에 대한 정의를 제대로 이해하지 못한다면 앞으로 연재될 글을 제대로 이해하지 못할수도 있다. 그럼 언제나 똑같은 멘트이지만 이글을 통해서도 해당 내용들에 대하여 자세히 이해할 수 없다면 당연히 다른 레퍼런스를 참조해서 이들에 대한 정확한 이해를 해야할것이다.

이는 비단 다음연재될 글들뿐만이 아닌 자바스크립트 Core 에 대한 이해에 필수적인 내용이기 때문에 반드시 이해하고 있길 바란다.



자바스크립트의 변수범위와 호이스팅

함수에 아랫쪽에 선언된 변수가 윗쪽으로 끌어올려지는 현상

면접 단골!
출력을 쓰시오
var num1=10;
function doA(){
console.log(num1);
num1=100;
}
doA();
console.log(num1);


함수가 아니라 조건식일 경우 전역으로 선언됨
if(true){
var color="blue";
}
alert(color); //blue



JavaScript 개체
https://msdn.microsoft.com/ko-kr/library/htbw4ywd(v=vs.94).aspx

join() /push()/ shift()/ concat()

join 메서드(Array)(JavaScript)

 

지정된 구분 문자열로 구분되는 배열의 모든 요소를 추가합니다.




arrayObj.join([separator]) 


arrayObj

필수 요소. Array 개체입니다.

separator

선택 사항입니다.결과 String에서 한 배열 요소와 다음 요소를 구분하는 데 사용되는 문자열입니다.생략하면 배열 요소들은 쉼표로 구분됩니다.


배열의 요소가 undefined 또는 null이면 공백 문자열로 처리됩니다.

다음 예제는 join 메서드를 사용하는 방법을 보여 줍니다


var a, b;
a = new Array(0,1,2,3,4);
b = a.join("-");
document.write(b);

// Output:
// 0-1-2-3-4

push 메서드(Array)(JavaScript)

 

배열에 새 요소를 추가하고 배열의 새 길이를 반환합니다.




arrayObj.push([item1 [item2 [. . . [itemN ]]]])


arrayObj

필수 요소. Array 개체입니다.

item, item2,. . ., itemN

선택 사항입니다. Array의 새 요소입니다.


push 및 pop 메서드를 사용하면 LIFO(후입 선출) 스택을 시뮬레이트할 수 있습니다.

push 메서드는 요소를 나타나는 순서에 따라 추가합니다.인수 중 하나가 배열이면 하나의 요소로 추가됩니다.둘 이상의 배열에서 요소를 결합하려면 concat 메서드를 사용합니다.

다음 예제에서는 push 메서드를 사용하는 방법을 보여 줍니다


var number;
var my_array = new Array();

my_array.push (5, 6, 7);
my_array.push (8, 9);

number = my_array.pop();
while (number != undefined)
   {
   document.write (number + " ");
   number = my_array.pop();
   }

// Output:
// 9 8 7 6 5


shift 메서드(Array)(JavaScript)

 

배열에서 첫 번째 요소를 제거하여 반환합니다.




arrayObj.shift( )


필수 arrayObj 참조는 Array 개체입니다.


즉, 배열에서 제거된 요소를 반환합니다.


다음 예제에서는 shift 메서드를 사용하는 방법을 보여 줍니다.


var arr = new Array(10, 11, 12);
while (arr.length > 0)
    {
    var i = arr.shift();
    document.write (i.toString() + " ");
    }

// Output: 
// 10 11 12

concat 메서드(Array)(JavaScript)

 

둘 이상의 배열을 결합합니다.




array1.concat([item1[, item2[, . . . [, itemN]]]]) 


array1

필수 요소.다른 배열을 연결할 Array 개체입니다.

item1,. . ., itemN

선택 사항입니다. array1의 끝에 추가할 항목입니다.


concat 메서드는 array1과 주어진 다른 항목 간의 연결을 포함하는 Array 개체를 반환합니다.

배열에 추가될 항목(item1 itemN)은 목록의 첫 번째 항목부터 순서대로 추가됩니다.항목 중 하나가 배열이면 그 내용이 array1의 끝에 추가됩니다.항목이 배열이 아니면 배열의 끝에 단일 배열 요소로 추가됩니다.

소스 배열의 요소는 결과로 나오는 배열에 다음 방식으로 복사됩니다.

  • 개체가 새 배열에 연결될 임의의 배열에서 복사되는 경우 개체 참조는 계속해서 같은 개체를 가리킵니다.새 배열 또는 원래 배열의 변경 내용은 나머지 배열에 영향을 줍니다.

  • 숫자 또는 문자열 값이 새 배열에 추가되는 경우 값만 복사됩니다.한 배열의 값을 변경해도 다른 배열의 값에는 영향을 주지 않습니다.

다음 예제에서는 배열과 함께 사용될 때 concat 메서드를 사용하는 방법을 보여 줍니다


var a, b, c, d;
a = new Array(1,2,3);
b = "dog";
c = new Array(42, "cat");
d = a.concat(b, c);
document.write(d);

//Output: 
1, 2, 3, "dog", 42, "cat"






함수를 배열로 선언 가능

이런것도 가능
var idx = prompt("index");
arr[idx]();

자바스크립트는 함수를 파라미터로 던질 수 있다.



// Splice를 이용하여 로또 만들기
var myLotto = [];
var aryLotto = [];
var idx = 0;

for (var i = 1; i < 46; ++i){ aryLotto.push(i);}
while (myLotto.length < 6){
idx = Math.floor(Math.random()*aryLotto.length);
myLotto.push(aryLotto[idx]);
aryLotto.splice(idx,1);
}
myLotto.sort(sortNumber);

function sortNumber(a, b) {
return a - b;
}

//myLotto.sort(function calc(a,b){
// return a-b;
//});
// document.write(myLotto);

console.log(myLotto.toString());



'IT > JavaScript' 카테고리의 다른 글

[Javascript] 이벤트 정리  (0) 2019.08.28
Javascript 부모창 id value 가져오기  (0) 2018.12.28
Google JavaScript Style Guide  (0) 2018.04.03
Javascript 페이지에서 데이터교환  (0) 2016.09.08
20160629 [JAVASCRIPT] json, cors  (0) 2016.06.29