반응형

closure(클로저)는 함수와 그 함수가 선언된 스코프(scope) 사이의 관계를 말합니다. closure는 함수가 정의될 때의 환경을 기억하고, 그 환경에서 정의된 변수에 접근할 수 있는 기능을 제공합니다.

JavaScript의 함수는 first-class citizen이므로, 변수에 할당하거나 다른 함수의 인자로 전달할 수 있습니다. closure는 이러한 특징을 이용하여 함수를 반환하거나 함수를 전달할 때, 함수가 정의된 스코프에서 선언된 변수에 접근할 수 있는 것을 가능하게 합니다.

이는 외부 함수가 종료되어도 내부 함수가 참조하는 변수들이 유지되어 외부 함수의 변수에 접근할 수 있게 합니다.

function outerFunction(x) {
  return function innerFunction(y) {
    return x + y;
  };
}

const add5 = outerFunction(5);
console.log(add5(3)); // 8

위의 코드에서 outerFunction은 x 값을 매개변수로 받습니다. 그리고 innerFunction 함수를 반환합니다. innerFunction 함수는 y 값을 매개변수로 받습니다.

그리고 add5 변수에 outerFunction(5)의 결과를 할당합니다. 이 결과는 innerFunction 함수입니다. 그러므로 add5(3)을 실행하면 innerFunction 함수가 실행되고 x+y의 결과인 8이 출력됩니다.

아래의 코드에서는 createCounter 함수가 closure를 생성합니다.

function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

createCounter 함수가 반환하는 함수는 count 변수에 접근할 수 있어서, counter 변수에 저장된 함수를 호출할 때마다 count 값이 1씩 증가합니다.

closure는 코드의 캡슐화(encapsulation)에 많이 사용됩니다. 내부 함수가 외부 함수의 변수에 접근할 수 있기 때문에, 외부 함수의 변수를 숨기고 내부 함수만을 통해서 접근할 수 있는 기능을 구현할 수 있습니다.
위의 소스에서 count 변수는 closure를 통해 은닉화 되었습니다.

closure는 애플리케이션의 구조화와 모듈화에 큰 도움이 될 수 있습니다. 예를 들어, 아래의 코드에서는 private 변수를 통해서 외부에서 접근할 수 없는 값을 저장할 수 있습니다.

function Person(name) {
  let privateName = name;
  
  return {
    getName: function() {
      return privateName;
    },
    setName: function(newName) {
      privateName = newName;
    }
  };
}

const person = Person("John");
console.log(person.getName()); // John
person.setName("Jane");
console.log(person.getName()); // Jane

closure를 사용하면, 객체의 내부 상태를 외부에서 변경할 수 없게 할 수 있습니다. 그리고 내부에서만 접근할 수 있는 메소드를 구현할 수 있어서, 애플리케이션의 코드를 깔끔하게 유지할 수 있습니다.

closure의 장단점

장점

  1. 변수의 유지

closure는 외부 함수의 변수를 저장하여 외부 함수가 종료된 후에도 변수를 사용할 수 있습니다. 이는 메모리 효율성을 높여줍니다.

  2. 은닉성

closure를 사용하면 외부 함수의 변수와 내부 함수를 숨길 수 있어 변수의 접근을 제어할 수 있습니다.

  3. 단일 책임 원칙

closure는 함수의 역할을 구분하여 각각의 역할이 담당하는 변수와 함수를 분리할 수 있습니다. 이는 단일 책임 원칙을 준수하는 코드를 작성할 수 있게 해줍니다.

단점

  1. 메모리 낭비

closure를 사용하면 외부 함수가 종료된 후에도 내부 함수가 참조하는 변수를 메모리에 저장해야 하므로 메모리 낭비가 생길 수 있습니다.

  2. 코드 가독성

closure를 많이 사용하면 코드가 복잡해지고 이해하기 어렵습니다. 따라서 클로저를 사용할 때에는 적절한 주석과 코드 구조를 갖추어야 합니다.

반응형
반응형

구독하고 있는 chris@gomakethings.com의 메일링 리스트로 온 내용을 번역했습니다.

Array.prototype.find() 메서드는 배열에서 콜백 함수로 전달한 테스트와 일치하는 첫 번째 항목을 찾습니다. 콜백은 배열의 현재 항목을 참조하는 참조 변수를 위한 인수를 제공합니다.

다음은 샌드위치 배열에서 참치를 찾는 간단한 예입니다.

let sandwiches = ['turkey', 'chicken salad', 'tuna', 'pb&j', 'egg salad'];

let tuna = sandwiches.find(function (sandwich) {
	return sandwich === 'tuna';
});

console.log(tuna); // logs "tuna"

항목을 찾지 못하면 undefined를 반환합니다.

let hamburger = sandwiches.find(function (sandwich) {
	return sandwich === 'hamburger';
});

console.log(hamburger); // logs undefined

Array.prototype.find() 메서드가 진짜 잘 작동하는 곳은 복잡한 배열입니다.

예를 들어, todo 객체가 포함된 배열을 가지는 JSON 파일을 반환하는 API가 있다고 가정해봅시다.

let todos = [
	{
		item: 'Wash the dog',
		added: 20180322,
		completed: false
	},
	{
		item: 'Plan surprise party for Bailey',
		added: 20180314,
		completed: false
	},
	{
		item: 'Go see Black Panther',
		added: 20180312,
		completed: true
	},
	{
		item: 'Launch a podcast',
		added: 20180305,
		completed: false
	}
];

어떻게 하면 'Go see Black Panther' 아이템이 언제 추가됐는지, 완료됐는지 확인할 수 있을까?

Array.prototype.find() 메서드가 없을 경우, 각각의 할 일을 반복하여 아이템을 확인하고, 일치하는 결과를 저장하고, 루프을 종료해야 합니다.

let item;
for (let todo of todos) {
	if (todo.item === 'Go see Black Panther') {
		item = todo;
		break;
	}
}

Array.prototype.find() 메서드를 사용할 경우, todo.item 속성이 'Go see Black Panther' 인 것을 확인하면 됩니다.

let item = todos.find(function (todo) {
	return todo.item === 'Go see Black Panther';
});
반응형
반응형

SQL서버에서 정수를 16진수로 변환하는 방법 입니다.

1. 정수를 16진수로 변경 하려면 BARBINARY 타입으로 CONVERT 한다 (SQL Server 2008 이상).

2. 16진수를 정수로 변경하려면 INT 타입으로 CONVERT 한다.
    단 16진수가 문자로 되어 있는 경우에는 VARBINARY로 CONVERT 한 후, 다시 INT 타입으로 CONVERT 한다.

-- 0x prefix가 있을 때:
SELECT CONVERT(INT, CONVERT(VARBINARY, '0x1FFFFF', 1)) 
-- 0x prefix가 없을 때:
SELECT CONVERT(INT, CONVERT(VARBINARY, '1FFFFF', 2))

3. 내장함수인 fn_varbintohexstr()를 사용 한다.

4. FORMAT() 함수를 이용 한다 (SQL Server 2012 이상).

반응형
반응형

Grid에서 특정 row를 선택하여 해당 row와 관련된 modeless 창을 띄우고 작업을 하는 도중,
원래 Form에서 Grid가 정렬되어 기존 row의 handle이 변경되었을 경우 단순히 FocusedRowHandle을 보관 했다가
찾아가는 방식은 사용할 수 없다(그리드 내에서 위치가 변경 되었으므로).
이때는 다음과 같이 DataSourceRowIndex를 보관 했다가, 해당 값으로 현재의 FocusedRowHandle 값을 찾아가야 한다.
DataSourceRowIndex는 DataSource내의 고유한 index이기 때문에 GridView에서 보여지는 형태와 관계없이 일정하게 유지 되므로 이 값을 가진 RowHandle을 찾아내는 방식이다.

// modeless 창을 띄우기 전에 현재 선택된 row의 DataSourceRowIndex를 보관
var rowIndex = gView1.GetFocusedDataSourceRowIndex(); 
.....
/*
  modeless 창을 띄우고 작업하는 도중, Grid가 정렬 되었다고 가정
*/
....
// modeless 창이 닫히고, 다시 원래의 FocusedRowHandle를 찾아가게 한다.
var rowHandle = GetRowHandleFromRowIndex(gView1, rowIndex);
gView1.FocusedRowHandle = rowHandle;
 
// DataSourceRowIndex를 가진 행을 찾아서 RowHandle 값으로 되돌린다.
private int GetRowHandleFromRowIndex(GridView gridView, int rowIndex) {
  int result = -1;
 
  for (int i = 0; i < gridView.DataRowCount; i++) {
    if (gridView.GetDataSourceRowIndex(i) == rowIndex) {
      result = i;
      break;
    }
  }
 
  return result;
}
반응형

+ Recent posts