728x90
Proxy : 대리

 

Proxy는 JavaScript에서 객체의 기본 동작(예: 속성 접근, 할당, 열거, 함수 호출 등)을 사용자 정의 동작으로 가로채서(trap) 조작할 수 있게 해주는 기능입니다.

즉, 객체에 대한 작업을 가로채서 그 작업이 수행되기 전, 수행된 후, 또는 작업을 완전히 대체하여 추가적인 로직을 실행할 수 있게 해줍니다. 이런 특징 때문에 Proxy는 다양한 고급 작업과 패턴에 유용하게 사용될 수 있습니다.

 

const target = {
  message1: "hello",
  message2: "everyone",
};

const handler1 = {};

const proxy1 = new Proxy(target, handler1);

proxy1.message1 = 'hi';
console.log('target', target);

위의 코드에서 target의 message1 속성의 값은 hi로 변경되게 된다.

 

아래 예제를 통해 Proxy로 할 수 있는 다양한 가능성을 살펴보겠다.

1. 속성 읽기 접근 제어

속성을 읽을 때마다 로그를 출력하도록 합니다. get은 속성값을 가져오기 위한 trap(가로채기)이다.

(...)
const handler1 = {
  get(target, prop, receiver) {
    console.log(`속성 '${prop}'에 접근함`);
    return Reflect.get(...arguments);
  }
};

const proxy1 = new Proxy(target, handler1);

console.log(proxy1.message1); // 속성 'message1'에 접근함 -> hello
console.log(proxy1.message2); // 속성 'message2'에 접근함 -> everyone

Proxy는 반드시 new 키워드로만 생성가능하다.

 

2. 속성 쓰기 접근 제어

속성에 값을 할당할 때 유효성 검사를 추가합니다. 예를 들어, message1에는 오직 문자열만 할당될 수 있게 합니다.

(...)
const handler1 = {
    set(target, prop, value) {
        if (prop === "message1" && typeof value !== "string") {
            throw new Error("message1은 문자열이어야 합니다.");
        }
        target[prop] = value;
        return true; // 성공적으로 값을 할당했음을 나타냄
    }
};

const proxy1 = new Proxy(target, handler1);

proxy1.message1 = "안녕하세요"; // 성공
try {
    proxy1.message1 = 123; // Error: message1은 문자열이어야 합니다.
} catch (e) {
    console.error(e.message);
}

 

3. 속성 존재 여부 확인

객체에 특정 속성이 있는지 확인할 때마다 로그를 출력합니다.

const handler1 = {
  has(target, prop) {
    console.log(`${prop} 속성이 객체에 존재하는지 확인`);
    return prop in target;
  }
};

const proxy1 = new Proxy(target, handler1);

console.log('message1' in proxy1); // message1 속성이 객체에 존재하는지 확인 -> true
console.log('message3' in proxy1); // message3 속성이 객체에 존재하는지 확인 -> false

 

이외에도 다양한 Handler Function을 통해 객체의 기본동작을 정의하고 유연하게 사용할 수 있다.

 

Proxy생성자와 Handler Function에 대해서는 다음 문서를 참고

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy

 

Proxy() constructor - JavaScript | MDN

The Proxy() constructor creates Proxy objects.

developer.mozilla.org

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

html + javascript 기초  (0) 2021.01.07
자바스크립트 - 의사 결정  (0) 2017.03.28
자바 스크립트 기초 - 함수, 메서드, 객체  (0) 2017.03.27
728x90

0. 샘플 소스

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
function fun1() {
	alert("안녕 자바스크립트");
	return;
}
function fun2(money) {
	alert("받은 동전 : " + money)
	return;
}
function fun3(money) {
	alert("무료음료수 전달")	
	return "커피";
}

function fun4(a, b) {
	alert("받은 동전" + a + b);
	alert("음료수 선택");
	return "사이다";
}
	
</script>
<body>
<h1>WebContent/js1/test3.html</h1>
<input type="button" value="출력버튼" onclick="fun1()">
<input type="button" value="값을 받아서 뽑기출력버튼" onclick="fun2(500)">
<input type="button" value="무료음료수받기" onclick="alert('전달받은 음료수: ' + fun3() )">
<input type="button" value="음료수받기" onclick="alert('받은 음료수: ' + fun4(500, 100) )">
</body>
</html>

위의 funtion 인 fun4에서 "받은 동전" + a + b와 같이 쓰면 문자열로 서로 연결된다.

 

이를 피하고 a와 b변수의 값을 더하고자 한다면 아래와 같이 수정한다.

function fun4(a, b) {
	alert("받은 동전" + (a + b) );
	alert("음료수 선택");
	return "사이다";
}​

 

1. 가변인자를 통한 함수 정의

(...)
<script type="text/javascript">
// 입력받은 값 평균 구하기
function fun4(...args) {
    let res = 0;    
    for (let i = 0; i < args.length; i++) {
        res += args[i];
    }    
    avg = res / args.length;
    return avg;
}
</script>
(...)
<input type="button" value="두수합리턴받아서 평균 구하기"
 		onclick="alert('리턴받은값 : ' + fun4(10, 20) )">

 

2. 내장함수

: 자바스크립트에서 기본적으로 제공하는 함수

ex) alert, confirm 등

 

1) alert

- alert는 리턴값이 없고 사용자에게 팝업창으로 알려주는 역할

var a = alert("메시지");
	alert(a);

- 리턴값이 없으므로 undefined 메시지가 뜸

 

2) confirm

- 사용자가 확인 / 취소를 선택할 수 있는 팝업을 제공

 

var r = confirm('확인/취소 선택하세요');
alert(r);

- 확인 시 true, 취소 시 false를 리턴

 

3) prompt

- 사용자에게서 입력받은 값을 반환, 입력값은 문자로 인식

var v = prompt("입력하세요", "입력란");
	alert(v);
alert(v + 100);	// 문자열로 더해져서 출력됨
alert(v * 100); // 곱하기는 숫자로 인식

 

4) parseInt

- 숫자 정수로 변환하는 함수

alert(parseInt(v) + 100);	

5) isNaN

- 숫자 / 문자열인지 판별하는 함수로 문자이면 true, 숫자면 false반환

(문자열과 숫자가 함께 포함되면 문자로 인식)

var isString = isNaN(v);
if (isString) {
	alert ('문자를 입력하셨습니다');
}
else {
	alert ('숫자를 입력하셨습니다');
}	

 

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

[JavaScript] Proxy  (0) 2024.04.03
자바스크립트 - 의사 결정  (0) 2017.03.28
자바 스크립트 기초 - 함수, 메서드, 객체  (0) 2017.03.27
728x90


타입 강제와 약한 형식화


자바스크립트는 내부적으로 데이터 타입을 변환하여 작업을 완료할 수 있다.

이를 type coercion (타입 강제) 이라고 한다.


'1' > 0 이라는 구문에서 문자열 1이 숫자 1로 강제 변환되고 true를 return할 수 있다.


강력한 형식화를 사용하는 일부 다른 프로그래밍 언어와 달리, 자바스크립트는 약한 형식화를 사용한다.


따라서 의도하지 않은 값을 만들어내는 것이 싫다면 동등 비교 연산자 ==, != 를 쓰는 것보다 

일치 비교 연산자 ===, !== 를 쓰는 것이 권장된다.



===, !== 는 같은 값인지 여부 뿐만 아니라 데이터 타입도 비교한다.




단축 평가 값


OR 연산자를 사용할 때는 true를 리턴할 가능성이 높은 코드를 첫번째 조건으로 작성하고,

AND 연산자를 사용할 때는 false를 리턴할 가능성이 높은 코드를 첫번째 조건으로 작성한다.


단축 평가 기버은 페이지 내에 요소가 존재하는지를 검사하는 용도로 활용이 가능하다.



자바스크립트에서 true와 false

자바스크립트에서 숫자 0이나 빈 값, 값을 대입하지 않은 변수는 false로 취급된다.


반면에 내용을 가진 문자열이나 0이 아닌 다른 숫자는 true이다.



단항 연산자에서 

if( document.getElementById('header') ) 라는 구문이 있다면


ifdocument.getElementById('header'== true ) 로 생각하기 쉽다.

하지만 boolean값인 true와 document.getElementById('header') 가 
리턴되는 객체(true로 취급될 순 있어도)는 엄연히 다른 값이다!

논리 연산자는 항상 true나 false를 리턴하지 않는다. 

처리를 중지하게 된 계기가 된 값을 리턴하거나, 
그 값이 실제로 boolean type이 아니더라도 true나 false로 취급될 수 있다.


예약된 데이터 타입

단순혹은 기본 데이터 타입인 String, Number, Boolean, Undefined, Null

복합데이터 타입인 Object



true, false는 boolean 값이므로 (false === 0)은 

type이 일치하지 않으므로 false를 return한다.


(undefined == null)이 true지만, (undefined === null)은 false이다. 

boolean과 마찬가지로 undefined도 하나의 형식이기 때문이다.





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

[JavaScript] Proxy  (0) 2024.04.03
html + javascript 기초  (0) 2021.01.07
자바 스크립트 기초 - 함수, 메서드, 객체  (0) 2017.03.27
728x90

함수의 매개변수와 인수의 비교


function getArea(width, height) {

return width * height;

}


위 함수내에서 변수 이름과 동일하게 동작하는 (width, height) 가 매개 변수이다.


wallWidth = 3;

wallHeight = 5;

getArea(wallWidth, wallHeight);


위에서 함수가 호출될 때 전달되는 값이 바로 인수이다.



함수로부터 여러 값 전달받기


1
2
3
4
5
6
7
8
9
function getSize(width, height, depth) {
  var area = width * height;
  var volume = width * height * depth;
  var sizes = [area, volume];
  return sizes;    
}
 
var areaOne = getSize(323) [0];
var volumeOne = getSize(323) [1];
cs


8행의 areaOne 변수는 3 * 2 의 연산결과인 사각형 면적을 저장하며, size 배열의 첫번째 값[0] 이다.




익명 함수와 함수 표현식


자바 스크립트 해석기가 표현식을 필요로 하는 곳에 함수를 전달하면, 이 함수는 표현식으로 처리된다. 

(var area = 3*5와 같은 선언이 아닌 함수를 대입하였다)


이런 함수를 함수 표현식이라고 하며, 함수 표현식을 사용할 때는 대부분 함수 이름을 생략한다.


1
2
3
4
5
var area = function (width, height) {
return width * height;
};
 
var size = area(34);
cs


위와 같이 함수의 선언과 함께, 변수에 저장할 때 함수 이름을 생략 가능하다. 

이처럼 이름이 없는 함수를 익명 함수(anonymous function)이라고 한다.


5행에서 이 익명 함수를 변수의 이름으로 호출하는 것을 볼 수 있다.



즉시 호출 함수 표현식 

IIFE(Immediately Invoked Function Expressions: “이피( Iffy )”라고 발음)


이름이 부여되지 않은 함수를 의미한다. 자바 스크립트 해석기가 함수 정의를 만났을 때 단 한번 실행된다.


1
2
3
4
5
var area = (function () { 
    var width = 3;
    var height = 2;
    return width * height;
() );
cs

위의 변수 area는 나중에 호출할 목적으로 함수를 저장하는 것이 아닌, 함수가 리턴한 값만 저장하게 된다.


초록색 괄호는 자바스크립트 해석기에게 함수가 즉시 호출되어야 함을 알린다.


빨간색 괄호그룹화 연산자 이며, 해석기가 전체 코드를 표현식처럼 취급하도록 하기 위해 둘러싼 괄호이다.



이러한 익명 함수와 즉시 호출 함수는 어떤 작업 내에서 단 한번만 실행될 필요가 있을 때 사용된다.

예를 들면 다음과 같다.


  • 함수를 호출할 때 인수로 전달하기 위해(호출할 함수에 전달할 값을 계산하기 위해)
  • 객체의 속성에 값을 대입하기 위해
  • 동일한 변수 이름을 사용하는 두 스크립트 간의 이름 충돌을 방지하기 위해
  • 이벤트 핸들러와 리스너 내부에서 이벤트가 발생했을 때 작업을 처리하기 위해

즉시 호출 함수는 주로 일련의 코드를 감싸기 위해 사용한다.
scope라는 개념 하에 익명 함수 내부에 선언된 모든 변수들은 스크립트의 다른 부분에 선언된 같은 이름의 변수로부터 보호된다.



변수의 범위 scope


함수내부에서 var 키워드를 이용해 함수 내부에 선언하면 해당 함수 내부에서만 사용할 수 있다. 

이를 지역 변수, 함수 수준 변수라고 하며, 지역 범위, 함수 수준 범위를 가지고 있다고 표현한다.


함수 바깥 부분에서 선언한 변수는 전역 변수이며, 전역 범위(global scope)를 가진다.


var 키워드를 사용하지 않아도 전역변수로 취급된다.




객체란?

현실 세계에서 인지한 물체에 대한 모델을 만들기 위해 변수와 함수를 그룹화 한 것.


객체의 일부로 선언된 변수는 속성(property)이라고 부른다.

객체의 일부로 선언된 함수는 메서드(method)라고 부른다.


다음은, 축약형 표기법을 이용해 객체 생성 

(app간에 데이터를 저장하거나 전송할 때 또는 페이지를 위한 정보를 설정하는 설정 객체나 전역 객체를 생성할 때 권장됨)


var hotel = {
  name : 'Quay',
  rooms : 40,
  booked : 25,
  checkAvailability : function() {
    return this.rooms - this.booked
  }
};


객체 내에서의 속성 이름을 key라고 부른다. 이 키를 통해 해당 값에 접근하기 때문에 중복은 불가하다.

: 왼쪽이 속성 이름이며, 오른쪽이 값이다. 여러 개의 속성을 선언할 때 쉼표로 구분한다.


객체에 접근할 때는 멤버 접근 연산자 . 을 통해 접근한다.


1
var hotelName = hotel.name;
cs


또는 아래와 같이 대괄호 문법을 통해 접근 가능하다.

1
var hotelName = hotel['name'];
cs



빈 객체를 축약형 표기법으로 생성

1
var hotelName = {};
cs



객체 수정하기


1
hotel.name = 'Park';
cs


대입 연산자를 통해 새로운 속성값을 대입하면 된다. 객체가 가지고 있지 않은 속성에 대입하려하면, 객체에 새 속성이 추가된다.

대괄호 문법으로도 속성값 변경이 가능하다.


1
hotel['name'= 'Park';
cs


속성 제거하기

다음과 같이 delete 키워드를 이용한다.


1
delete hotel.name;
cs


속성 값만 제거하기

다음과 같이 빈 문자열을 대입한다.

1
hotel.name = '';
cs



객체 생성자


function Hotel(name, rooms, booked) {
  this.name = name;
  this.rooms = rooms;
  this.booked = booked;
  
  this.checkAvailability = function() {
    return this.rooms - this.booked;
  }
}

위 함수는 호텔을 표현하는 새 객체를 만들기 위한 템플릿처럼 사용된다.
객체 생성자 함수의 이름은 주로 대문자로 시작한다. (일반적으로 함수 이름은 소문자로 시작한다)

객체 생성자에서 각각의 구문은 새로운 속성이나 메소드를 대입하는 것이므로 semi-colon으로 끝을 맺는다.

new 키워드를 이용한 객체 생성

quayHotel과 parkHotel 객체 생성,  Hotel('Quay'4025)는 생성자 함수이다.

var quayHotel = new Hotel('Quay'4025);
var parkHotel = new Hotel('Park'12077);


아래 예제에서는 생성자 함수를 이용해 hotel 이란 이름의 빈 객체를 생성한다.
객체 생성후엔 속성과 메소드를 대입하는데, 이미 가지고 있는 속성이 있다면 값을 덮어 쓰게 된다.

// Set up the object
var hotel = new Object();

hotel.name = 'Park';
hotel.rooms = 120;
hotel.booked = 77;
hotel.checkAvailability = function() {
  return this.rooms - this.booked;  
};

var elName = document.getElementById('hotelName'); // Get element
elName.textContent = hotel.name;                   // Update HTML with property of the object

var elRooms = document.getElementById('rooms');    // Get element
elRooms.textContent = hotel.checkAvailability();   // Update HTML with result of method




객체 생성자 표기법을 이용해 객체 생성 및 사용하기


// 호텔 객체를 위한 생성자 함수 템플릿을 정의

function Hotel(name, rooms, booked) {
  this.name = name;
  this.rooms = rooms;
  this.booked = booked;
  this.checkAvailability = function() {
    return this.rooms - this.booked;
  };
}


// 두 개의 다른 호텔 객체 인스턴스 생성

var quayHotel = new Hotel('Quay'4025);
var parkHotel = new Hotel('Park'12077);


// 이미 존재하는 변수에 += 연산자를 사용해 다른 데이터를 덧붙인다.
var details1 = quayHotel.name + ' 남은 방: ';
    details1 += quayHotel.checkAvailability();
var elHotel1 = document.getElementById('hotel1');
elHotel1.textContent = details1;

var details2 = parkHotel.name + ' 남은 방: ';
    details2 += parkHotel.checkAvailability();
var elHotel2 = document.getElementById('hotel2');
elHotel2.textContent = details2;



한글 때문에 html의 글자가 깨진다면 html 소스에 다음 코드를 추가한다.

<meta charset="utf-8">


속성을  추가하거나 제거하기
이미 hotel 객체의 인스턴스를 생성한 후에도 속성을 추가하거나 제거할 수 있다.

var hotel = {
  name : 'Park',
  rooms : 120,
  booked : 77
};

// gym, pool 속성을 추가하고 boolean 값을 대입 후 booked 속성을 제거

hotel.gym = true;
hotel.pool = false;
delete hotel.booked;




this 키워드


var shape = {
  width: 600,
  height: 400,
  getArea: function() {
    return this.width * this.height;
  }
}
이 키워드는 항상 단 하나의 객체를 참조하며, 함수를 실행하고 있는 객체를 가리킨다.
바꿔 말해, 함수 내부에서 this 키워드가 사용될 때, this 키워드는 함수를 감싸는 함수가 소속된 객체를 가리킨다는 것이다.

한 함수가 다른 함수 내에 중첩되어 있는 경우에는, 첫번째 함수 내의 변수에 this 키워드의 값을 저장해두고, 

중첩된 함수내에서 이 변수를 this 키워드 대신 사용하는 것이 권장된다.



function windowSize() {
  var width = this.innerWidth;
  var height = this.innerHeight;
  return [height, width];
}

스크립트의 최상위 수준 (다른 객체나 함수 내부가 아닌 곳)에 함수를 선언하면, 이 함수는 global scope 혹은 global context에 포함된다.

이 global context에 속한 객체는 window 객체이므로 this 키워드를 사용하면 window 객체를 가리키게 된다.



아래 예제에서는 축약형 표기로 객체를 생성했다. 하지만 전역 범위에 선언된 showWidth() 함수는 객체의 멤버가 아니므로,

이 경우 전역 변수 width 를 가리킨다.


var width = 600;


var shape = {
    width: 300
};


var showWidth = function() {
  document.write(this.width);
};


showWidth();



메서드로서의 함수 표현식


아래 예제의 11행은 익명 함수가 shape 객체의 메서드로 사용될 것이며, 그 이름이 getWidth() 함수가 될 것임을 표현한 것이다.

getWidth() 함수를 호출하면, 실제로 showWidth() 함수가 호출된다. 
이 때는 그 함수가 속한 객체가 shape이므로 shape 객체의 속성 width의 값 300을 가리키게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
var width = 600;
 
var shape = {
    width: 300
};
 
var showWidth = function() {
  document.write(this.width);
};
 
shape.getWidth = showWidth;
shape.getWidth();
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
var funcThis = null
 
function Func(){
    funcThis = this;
}
var o1 = Func();
if(funcThis === window){
    document.write('window <br />');
}
 
var o2 = new Func();
if(funcThis === o2){
    document.write('o2 <br />');
}
cs


결과

1
2
window 
o2
cs



6행에서는 함수를 호출한 것이므로 함수에서의 this는 그 함수가 속한 객체, 여기서는 window 객체를 가리킨다.

11행에서는 new 키워드를 통해 생성자를 통해 만들어진 객체에서의 this 는 그 만들어진 객체 자신을 가리킨다.



배열도 객체이다


호텔 방의 가격을 객체로 표현한 경우


costs = {
  room1: 420,
  room2: 460,
  room3: 230,
};


이 경우 room1~3 속성과 각각의 값을 가진다.

호텔 방의 가격을 배열로 표현한 경우


costs = [420460230];

이 경우 index 0~2 와 각각의 값을 가진다.


객체 내에 배열을 가지거나 배열 내에 객체를 가질 수 있다.

객체 내의 배열
costs.room1.items[0];

배열 내의 객체
costs[2].phone;


배열의 2번째 index  { accom: 620, phone: 60 }




내장 객체

브라우저 객체 모델, 문서 객체 모델, 전역 자바스크립트 객체



브라우저 객체 모델

window.screen.width;


문서 객체 모델

documnet.getElementById('one');


전역 자바스크립트 객체

hotel.toUpperCase();    


: string 객체가 전역 객체로 제공되며 문자열 자체가 마치 String 객체인 것처럼 동작하기 때문에 wrapper object라고도 함



예약된 데이터 타입


단순혹은 기본 데이터 타입인 String, Number, Boolean, Undefined, Null

복합데이터 타입인 Object



배열이 객체라는 것은 .length라는 속성을 통해 확인할 수 있다.




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

[JavaScript] Proxy  (0) 2024.04.03
html + javascript 기초  (0) 2021.01.07
자바스크립트 - 의사 결정  (0) 2017.03.28

+ Recent posts