본문 바로가기

HTML, CSS, ECMA6/자바스크립트(Java Script)

[자바스크립트(JavaScript)] 시작하기

자바스크립트(JavaScript) 시작하기


실행 환경 {

​ ‘IDE’ : ‘Eclipse’

​ ‘Java_Version’ : ‘JDK 1.8’

​ ‘Browser’ : ‘Chrome’

}

  • 객체 기반으로 만들어진 스크립트 언어
  • 브라우저에서 작동하므로 익명화된 함수를 사용함 (재사용되지 않는 함수에 대해서)

기본 기능

웹페이지에 alert , console.log 사용하기

파일명 : hello.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script>
console.log("hello world")
alert("Hello World");
</script>

</head>
<body>
<h1>Hello World</h1>
</body>
</html>

데이터 타입 알아보기

파일명 : ex1.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
var number1 = 5;
console.log(number1 + ':' + typeof(number1));
</script>
</head>
<body>
</body>
</html>

>> 5number

var 로 생성된 number1 데이터 타입은 number 타입으로 생성된 것을 알 수 있다.

그렇다면 number 타입이 존재한다는 것이므로 다음의 방식을 추가해보자

var number2 = new Number(10);
console.log(number2 + ':' + typeof(number2));

>> 10object

이번에 생성된 number2는 object 타입으로 생성되었다.

new 를 사용해서 만들어지는 변수는 모두 object로 생성된다는 것을 알 수 있다.

그렇다면 둘이 연산이 가능할까?

console.log(number1 + number2);
>> 15

확인 결과, 둘의 연산이 된다는 것을 알 수 있다.

다만, 현 단계에서는 왜 둘의 연산이 되는 지는 나중에 알아보고 javascript가 가지고 있는 내장타입에 대해서 더 자세히 알아보자

// 내장타입(number, boolean, string, function, date, array....)
var n = 10;
var f = 3.14;
var b = true;
var s = 'hello world';
var fn = function(){};
var a = []; //array 타입은 없다.
var o ={};

console.log(n + ":" + typeof(n));
console.log(f + ":" + typeof(f));
console.log(b + ":" + typeof(b));
console.log(s + ":" + typeof(s));
console.log(fn + ":" + typeof(fn));
console.log(a + ":" + typeof(a));
console.log(o + ":" + typeof(o));

>>
10:number
3.14:number
true:boolean
hello world:string
function(){}:function
 :object
[object Object]:object

new 생성자함수()를 사용해서 객체를 생성하면 object로 생성된다.

console.log("------------------------------------");
// new 생성자함수()를 사용해서 객체를 생성할 때,
var n2 = new Number(5);
var s2 = new String('hello world');
var f2 = new Number(3.14);
var b2 = new Number(true);
var fn2 = new Function('a', 'b', 'return a + b;');
// fn2(a, b){return a+b;}
var a2 = new Array();
var o2 = new Object();

console.log(n2 + ":" + typeof(n2));
console.log(f2 + ":" + typeof(f2));
console.log(b2 + ":" + typeof(b2));
console.log(s2 + ":" + typeof(s2));
console.log(fn2 + ":" + typeof(fn2));
console.log(a2 + ":" + typeof(a2));
console.log(o2 + ":" + typeof(o2));

>>
------------------------------------
5:object
3.14:object
1:object
hello world:object
function anonymous(a,b) {return a + b;}:function
 :object
[object Object]:object

위에서 확인한 내장타입의 객체와 New 생성자함수()를 통해서 오브젝트는 어떤 차이점이 있을까? 결론부터 이야기하자면 내장타입의 객체는 확장이 불가능하고 New 생성자함수()를 통해 만들어진 오브젝트는 확장이 가능하다.

// 내장타입의 객체는 확장이 불가능하다.
console.log("------------------------------------");
n.myVal = 20;
console.log(n.myVal);
>> undefined

// 오브젝트 타입의 객체는 확장이 가능하다.
n2.myVal = 20;
console.log(n2.myVal);
>> 20

이 외에도 브라우저가 가지고 있는 내장객체에 대해서 간단하게 알아보자.

// 브라우저 내장 객체 console
console.log("------------------------------------");
console.log('-log-')
console.warn('-warn-')
console.error('-error-')
console.info('-info-')

이처럼 내장타입, 오브젝트타입, 브라우저가 가지고 있는 내장객체에 대하여 알아보았다.

다만, 내장객체 확장을 확인하는 과정에서 undefined 라는 리턴 값은 무엇을 의미하는 것인지 궁금하다. 따라서 undefined과 null은 무슨 차이가 있는 지 알아보자.

결론부터 말하자면 null은 변수에 값이 셋팅되었으나 null이라는 객체가 가르키는 변수가 없는 것을 의미하며 undefined는 아예 변수가 없는 것을 의미한다. 즉 요청한 변수를 찾았으나 정의된 곳이 없다는 것을 뜻한다.

파일명 : ex2.html

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
<script>
var myVar1;
var myVar2 = null;

console.log(myVar1)
console.log(myVar2)
</script>
</head>
<body>

</body>
</html>

>> undefined
>> null

하지만 null 과 undefined을 비교해보면 결과가 의아하다.

// ==(equality, 값의 등치성, 형변환)  <> !=
console.log(myVar1 == myVar2);
>> true
// 즉 값이 null인 것과 undefined는 모두 없는 값으로 동일하다. 

console.log(myVar1 === myVar2);
>> false 

null 과 undefined 에 대하여 명확한 비교가 불가능하다. java와는 다르게 엄격하지 않아서 유연성을 가지고 있다는 점이 장점으로 작용할 수 있지만 단점으로도 작용할 수 있으니 이 점을 유의하여 사용하길 바란다.

그렇다면 명확한 타입 선언을 하지 않고도 유연하게 연산, 비교할 수 있는 자바스크립트의 객체들은 어떻게 형변환이 이루어지는 지 알아보자.

// ==(equality, 값의 등치성, 형변환)  <> !=
console.log("2" == 2);
console.log(true == 1);
console.log("abc" == new String('abc'));

// 형변환 테스트 
console.log("2" + 2);
console.log(2 + "2");
console.log(true + 101);
console.log("abc" + new String('abc'));

>> true
>> true
>> true
>> 22
>> 22
>> 102
>> abcabc

number타입은 string 타입으로 형변환되었음을 확인했으며 모두 연산이 진행된다는 것을 알 수 있다. 따라서 string과 number 타입으로 다른 상황에서 형변환이 된다면 number는 string타입으로 형변환이 되어 유연하게 연산이 가능하다.

/// ===(!==, identity, 객체의 동일성, 형변환x)
console.log("2" === 2);
console.log(true === 1);
console.log("abc" === new String('abc'));

>> false
>> false
>> false

객체가 동일한 지 비교하는 과정에서는 형변환이 진행되지 않았다.

다만 기존 자바에서 타입을 명시해주었으므로 명확하게 하기 위해서 아래와 같이 타입을 엄격하게 맞추는 것을 추천한다.

// 추천 :
// == 연산자를 사용할 때는 엄격하게 형변환을 해서 두 피연산자의 타입을 맞춘다.
str = "5";
console.log(parseInt(str) == 5);

변수의 범위

변수의 범위는 어떻게 정의가 되는 지 확인해보자

함수 내부에 변수를 선언하는 경우에는 함수 내부에서 변수가 생성되며 함수 내부에서 변수를 선언하지 않는 경우에는 외부에서 탐색 후 찾아온다.

// 변수 범위(Scope)
// 1. var 사용 여부에 영향을 받는다.
// 2. 특히 local(함수 내부) 
var i = 5;
var f = function(){
    i = 20;
    console.log(i)
    i = i -1;
}
f();
console.log(i);

>>20
>>19

위와 같이 선언되는 경우는 함수 내부에서 변수를 선언하지 않았으므로 외부에서 변수를 가져와서 ‘20’ 을 넣어준 후 global 형식으로 사용이 된다.

하지만 아래와 같이 함수 내부에서 변수를 선언하는 경우에는 외부에 선언된 i의 값과 함수 내부의 i의 값은 별도로 관리가 된다.

var i = 5;
var f = function(){
    var i = 20;
    console.log(i)
    i = i -1;
}
f();
console.log(i);

>>20 
>>5

따라서 혼란을 방지하기 위하여 함수 내부에서 변수를 선언하고 파라미터로 변수를 받는 방식으로 진행할 수 있도록 하는 것을 추천한다.

자바스크립트의 코드 읽는 방식

// statement
// js engine이 읽어서 실행하는 단위
// \n or ;(세미콜론) 단위로 읽어서 실행한다.
var i = 5;
var f = function(){
    var i = 20;
    console.log(i)
    i = i -1;
}
// 세미콜론 단위로 나뉘어졌기 때문에 위와 동일하게 실행된다. 
f(); console.log(i);

전역(global) 객체 알아보기

// 전역(global) 객체
console.log('--------------------------')
var s= 'hello world';
console.log(window.s);

var o = {};
o.name = '둘리';
o.age = new Number(10);
o.age.leap = 9;

console.log(window.o);
console.log(window.o.name);
console.log(window.o.age);
console.log(window.o.age.leap);

>> {name: "둘리", age: Number}
>> 둘리
>> Number {10, leap: 9}
>> 9

이를 객체가 가진 변수들의 값으로 표현하자면 아래의 표와 같다.

변수명
o 객체 위치
o에 속한 변수명
name ‘둘리’
age 10을 담은 객체 위치
o.age에 속한 변수명
leap 9

자바스크립트에서 데이터가 움직이는 방식인 Json 방식으로 표현하자면 다음과 같다.

var o2 = {
        'name' : '둘리',
        'age' : {
            'value' : 10,
            'leap' : 9
        }
}

자바스크립트에서 객체를 확장하며 사용한다는 점을 알게 되었다. 그렇다면 객체에 대해서 좀 더 자세히 알아보자.

우선은 객체를 생성하는 방법에 대해 알아보자

// 객체(type object)를 생성하는 방법1
// new 키워드를 사용하는 방법
var o1 = new Object();
o1.name = '둘리';
o1.age = '10';
console.log(o1);

//객체(type object)를 생성하는 방법2
// literal 사용하기
var o2 = {}; //오브젝트를 만드는 literal
o2.name = '마이콜';
o2.age = '102';
console.log(o2);

//객체(type object)를 생성하는 방법3
//(J)ava(S)cript (O)bject (N)otation = JSON
var o3 = {
        'name' : '또치',
        'age' : '12',
}; 
console.log(o3);


//객체(type object)를 생성하는 방법4
//커스텀 "생성 함수"를 만드는 방법
var f = function(){
    console.log('보통 일반 함수')
};

// 생성 함수의 이름은 일반 함수와는 다르게 변수명으로 구분될 수 있게끔 카멜 표기법으로 작성하는 관례를 따른다. 
var MyObject = function(name, age){
    console.log('생성자 함수')
    this.name = name;
    this.age = age;
};

var o4 = new f();
console.log(o4);
var o5 = new MyObject('아저씨', 40);
console.log(o5);

// 따라서 보통 함수와 생성자로 사용될 함수는 사용될 시 다음과 같은 목적으로 사용된다. 
f(); // var o4 = new f(); (X)
var o5 = new MyObject('아저씨', 40); //Myobject('아저씨', 40); (X)

// 생성자 함수는 쉽게 생각하면 자바에서 클래스 형식으로 사용되며 인스턴스를 만들어낸다고 생각하면 되나, ES6에서 class를 지원해주게 되었음. 다만 함수의 특성 상 return을 하지 않음.

prototype 기반의 상속을 통해 객체지향 구현 ( 속성, 함수 공유 )

var MyObject = function(name, age){
    console.log('생성자 함수')
    this.name = name;
    this.age = age;
};
MyObject.prototype.school= 'bit academy';
MyObject.prototype.course= 'cafe24';

console.log(MyObject);

// o6 인스턴스에는 prototype으로 설정이 된 객체 내 변수에 대해서 따로 선언을  하지 않았으나 위에서 설정한 값으로 나타남
// 이러한 작업이 되는 이유는 인스턴스객체에서 변수가 없다면 생성자의 proto타입에서 객체를 가져오기 때문이다.
var o6 = new MyObject('길동', 20);
console.log(o6);
console.log(o6.school);
console.log(o6.course);

// 하지만 아래와 같이 school 변수를 변경하여 주면 proto type의 값이 변하는 게 아니라 o6에 해당하는 변수가 설정된다.
o6.school = 'sds';
console.log(o6.school);

// o7의 값은 proto에서 설정된 값이 변하지 않았다는 것을 증명하는 내용이다.
var o7 = new MyObject('길동', 20);
console.log(o7);
console.log(o7.school);
console.log(o7.course);

객체에 대하여 잘 이해하였는 지 확인하기 위하여 실습 문제를 풀어보겠습니다.

파일명 : rect.js

/**
 *   Rect 생성자 함수
 */

var Rect = function(x1, y1, x2, y2, bg){
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.bg = bg;
}

Rect.prototype.show = function(){
    document.write(
        "<div style='position:absolute; " +
        "left:" + this.x1 + "px; " + 
        "top:"  + this.y1 + "px; " +
        "width:" + (this.x2-this.x1) + "px; " + 
        "height:" + (this.y2-this.y1) + "px; " + 
        "background-color:" + this.bg + "'>" +
        "</div>");
}

파일명 : ex4.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src='rect.js' type="text/javascript"></script>
<script>
window.onload = function(){
    var rects = [
        new Rect(100, 100, 200, 300, "RGB(0, 0, 255)"),
        new Rect(250, 250, 400, 400, "#f00")
    ]

    var index = 0;
    var intervalId = setInterval(function(){
        if(index >= rects.length){
            clearInterval(intervalId);
            return;
        }
        rects[index++].show();
//        rects[index].show();
//        index++;
    }, 1000);
}
</script>
</head>
<body>
</body>
</html>

ex4.html을 실행시키면 박스 2개가 표시되는 것을 볼 수 있다.

번외 - node.js linux에서 시작해보기(추후 자세하게 포스팅 예정)

실행 환경 {

​ ‘linux’ : ‘CentOS 6.9’

​ ‘가상환경’ : ‘VirtualBox’

​ ‘nodejs_version’ : ‘v0.10.48’

}

# RHEL 7 설치하기 

[root@localhost ~]# rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

# npm - Node Package Manager 를 설치하면 Node.js 도 같이 설치된다.
[root@localhost ~]# yum install -y npm

# 버전 확인하기 
[root@localhost ~]# node --version
v0.10.48

# 디렉토리 생성 및 테스트 파일 만들기 
[root@localhost dowork]# mkdir js
[root@localhost dowork]# cd js/
[root@localhost js]# vi hello.js

#### hello.js editing #### 
console.log("hello world")

[root@localhost js]# node hello.js
hell world

node.js 설치 참고

# 이클립스에서 사용중인 html에서 hello.js 를 가져와서 사용하기 
<script src='hello.js'>
console.log("hello world")
</script>

간단하게 웹서버를 node js로 만들어보기

#리눅스에서 간단하게 만들 웹서버 js 만들기
[root@localhost js]# vi simple-server.js
var http = require('http');

httpd = http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end('Hello World111');
})

httpd.listen(9999, '0.0.0.0', function(){  
    console.log('server starts');
});
[root@localhost js]# node simple-server.js 
server starts
#웹서버에서 리눅스 192.168.1.49:9999/ (ip주소) 로 접근

간단하게 웹서버 만들기 참고


2019-07-04 추가 내용

  1. Primitive data type 은 Number, String, Boolean, Null, undefined

  2. Array, Date, Math, Regexp, function, object : 객체

  3. Number, String, Boolean : 유사 객체(3가지 타입은 다른 기능이 추가적으로 있음.)

  4. class free: class가 없어도 객체 생성이 가능하다.

  5. 객체가 객체를 포함하기 쉬운 구성이다. 따라서 그래프, 트리, 맵 등을 쉽게 구현할 수 있다.

  6. 프로토 타입은 객체 속성을 다른 객체에 상속해줄 수 있는 특성이 있다.

    (객체에서 속성 못찾으면 프로토 타입에서 찾기 때문) : 초기화 시간 단축, 메모리 절약

    _poroto_

    a {

    ​ value : abc

    ​ items : {

    ​ item1 : {

    ​ detail info : blar

    ​ }

    ​ }

    }

  7. object literal => JSON

  8. immutable