본문으로 건너뛰기

jsonp function

· 약 1분

jsonp (json with padding)은 다른 서버의 데이터를 내 브라우저에서 호출하기 위해 사용한다. client 에서 callback 함수명과 전송할 값을 같이 보내어 server 에서 callback 함수 안에 data 를 담아 반환하는 방식이다.

전송할 값을 보낼 때, script 태그를 사용한다.

소스

function jsonp(url, callback) {
const callbackName = "jsonp_" + Math.round(100000 * Math.random());
window[callbackName] = function (data) {
delete window[callbackName];
document.body.removeChild(script);
callback(data);
};

const script = document.createElement("script");
script.src =
url + (url.indexOf("?") >= 0 ? "&" : "?") + "callback=" + callbackName;
document.body.appendChild(script);
}

stackoverflow 에서 가져온 소스인데 현재 출처를 찾을 수 없다.

설명

임의의 함수명으로 callback 함수를 생성한 뒤 script 태그를 생성해 server 와 통신한다.

예제

jsonp("http://aaa.com?data=" + data, function (result) {
console.log(result);
});

여담

jQuery 가 있다면 jQuery ajax의 dataType 을 jsonp 로 설정해주면 되고, 요새는 CORS 를 적용해 그냥 호출하는 방식으로 가는 추세다.

Object freeze, seal, preventExtensions - 객체 수정 제어

· 약 2분

es5 부터 객체의 수정을 제어할 수 있다. ie9 부터 지원하고, ie8 은 es5-sham을 추가하면 된다.

freeze method

객체를 불변으로 만든다.

예제

const frozenObject = {
value1: 1,
value2: 2,
};

Object.freeze(frozenObject);
console.log(Object.isFrozen(frozenObject)); // true

// 삭제 불가
delete frozenObject.value1;
console.log(frozenObject.value1); // 1

// 변경 불가
frozenObject.value2 = 3;
console.log(frozenObject.value2); // 2

// 객체 추가 불가
frozenObject.value3 = 3;
console.log(frozenObject.value3); // undefined

seal method

확장, 축소는 불가능하지만 writable 쓰기 가능하다.

예제

const sealedObject = {
value1: 1,
value2: 2,
};

Object.seal(sealedObject);
console.log(Object.isSealed(sealedObject)); // true

// 삭제 불가
delete sealedObject.value1;
console.log(sealedObject.value1); // 1

// 변경 가능
sealedObject.value2 = 3;
console.log(sealedObject.value2); // 3

// 객체 추가 불가
sealedObject.value3 = 3;
console.log(sealedObject.value3); // undefined

preventExtensions method

확장만 불가능하다.

예제

const preventExtensionObject = {
value1: 1,
value2: 2,
};

Object.preventExtensions(preventExtensionObject);
console.log(Object.isExtensible(preventExtensionObject)); // false

// 삭제 가능
delete preventExtensionObject.value1;
console.log(preventExtensionObject.value1); // undefined

// 변경 가능
preventExtensionObject.value2 = 3;
console.log(preventExtensionObject.value2); // 3

// 객체 추가 불가
preventExtensionObject.value3 = 3;
console.log(preventExtensionObject.value3); // undefined

설명

불변하게 하려면 얼리고, 수정이 가능하게 하려면 봉인하고 추가만 불가능하게 하려면 확장방지하자

client 에서 객체 변조를 못하게 전역변수를 얼려버리자

여담

freeze 는 중첩된 object 에 적용이 안 되는데, 이 때 deepFreeze 함수를 사용해 재귀적으로 객체를 얼려버리면 된다.

deepFreeze method

mdn을 참조했다.

소스

function deepFreeze(obj) {
if (!Object.isFrozen(obj)) {
Object.freeze(obj);
}

for (const key in obj) {
if (
{}.hasOwnProperty.call(obj, key) ||
!(
typeof obj[key] === "function" ||
(typeof obj[key] === "object" && !!obj[key])
)
) {
continue;
}

deepFreeze(obj[key]);
}
}

Javascript 기본값 연산자 (축약된 삼항연산자)

· 약 1분

Javascript 기본값 연산자 (축약된 삼항연산자)

한번 쓰면 헤어나올 수 없는 기본값 연산자에 대해 알아보자.

소스

// JavaScript syntax to set a default value
const text = someString || "default text";
const text2 = someString || someString2 || "default text2";

설명

someString 이 있으면 someString 을 반환, 아니면 default text 를 반환한다. 계속 붙혀나가면서 쓸 수 있다.

php7 에서는 해당 기능이 추가되었다. || 대신에 ?? 를 사용하면 된다.

lodash 에선 defaultTo를 사용하면 된다.

링크 클릭시 return false가 페이지에 그대로 출력될 때

· 약 1분

링크를 클릭했는데, 페이지에 return false;가 찍혀나오는 경우가 있다.

소스

<script>
function test() {
if (true) {
return false;
}
}
</script>

<!-- 페이지에 return false;가 출력됨 -->
<a href="javascript:test();">테스트</a>

<!-- 대체 -->
<a href="javascript://" onClick="test();">테스트</a>

설명

a href 속성 안에 javascript 를 사용시 발생한다. javascript 호출문인 onClick 을 이용하자.

페이징시 Row의 순번(인덱스) 구하기

· 약 1분

전체 레코드 수와 현재 페이지 번호, 페이지에 표시되는 레코드의 수를 안다면 쉽게 구할 수 있다.

소스

let totalCount;
let currentPageNum;
let shownRowNum;

for (let i = 0, len = data.length; i < len; i++) {
const index = Number(totalCount) - (i + (currentPageNum - 1) * shownRowNum);
}

여담

매번 공식을 알아내는게 귀찮아서 포스팅

Cross Domain Login 중 세션 생성시 IE 오류

· 약 1분

aaa.com 에서 bbb.com 의 세션을 jsonp 방식을 활용해서 생성하고 싶을 때, 유독 IE 에서만 세션 생성이 안되는 경우가 있다.

이는 P3P (Platform for Personal Preferences) 규약이 적용되어 세션을 가져오지 않는 것인데, 아래와 같은 방법으로 해결할 수 있다.

소스

<!-- 세션을 만들어줄 서버에서 P3P 헤더를 설정 -->
<?php
header('P3P: CP="CAO PSA OUR"');
?>

<!-- 세션을 가지고 오는 클라이언트 요청-->
<script>
$.ajax({
url:'cross domain session create url',
type:'post',
data:{
token1 : 'token1',
token2 : 'token2'
},
dataType:'jsonp'
}).then(function (result) {

});
</script>

가장 빠른 배열 중복 제거 알고리즘

· 약 1분

가장 빠른 배열 중복 제거 알고리즘

통계 사용시에 중복을 제거해야하는 경우가 있다.

소스

/*
@author http://www.shamasis.net/2009/09/fast-algorithm-to-find-unique-items-in-javascript-array/
*/

// prototype
Array.prototype.unique = function () {
let o = {},
i,
r = [];
const l = this.length;

for (i = 0; i < l; i++) {
o[this[i]] = this[i];
}

for (i in o) {
r.push(o[i]);
}

return r;
};

// function
const uniqueArray = function (arr) {
let o = {},
i,
r = [];
const l = arr.length;

for (i = 0; i < l; i++) {
o[arr[i]] = arr[i];
}

for (i in o) {
r.push(o[i]);
}

return r;
};

예제

let testArray = [1, 2, 1, 3];

testArray = testArray.unique();
testArray = uniqueArray(testArray);

console.log(testArray); // [ 1, 2, 3 ];

여담

언더스코어를 알게된 후로는 lodashuniquniqBy를 사용한다.

Javascript Unix Timestamp

· 약 1분

API 통신시 Unix Timestamp가 필요한 경우가 있다.

소스

// === PHP time();
const timestamp = Math.round(new Date().getTime() / 1000);
// 또는
// new Date().getTime() 을 Date.now() 로 바꿀 수 있다.

여담

lodash 라이브러리를 사용하면 _.now() 함수로 현재 타임스탬프를 가져올 수 있다. 소스처럼 1,000으로 나눠줘야한다.

숫자 3자리 단위로 comma 추가 - 정규식 활용

· 약 1분

소스

// function
function comma(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

// prototype
Number.prototype.format = function () {
return this.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
};

설명

첫번째는 함수 호출방식이고, 두번째는 NumberValue.format(); 으로 호출하면 된다.

숫자를 한글 숫자로 변환

· 약 2분

가끔 견적서에 한글 숫자를 써야할 때가 있다.

소스

/**
* [num2han 숫자를 한글로 변환]
* @param {[integer]} num [숫자]
* @return {[string]} [한글 숫자]
* @author http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=14981
*/
const num2han = function (num) {
let i,
j = 0,
k = 0;
const han1 = ["", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구"];
const han2 = ["", "만", "억", "조", "경", "해", "시", "양", "구", "간"];
const han3 = ["", "십", "백", "천"];
let result = "";
let hangul = String(num);
let pm = ""; // 부호
let str = [],
str2 = "";
const strTmp = [];

if (Number(num) === 0) {
return "영";
}

if (hangul.substring(0, 1) === "-") {
pm = "마이너스 ";
hangul = hangul.substring(1, hangul.length);
}

if (hangul.length > han2.length * 4) {
return "too much number";
}

for (i = hangul.length; i > 0; i = i - 4) {
str[j] = hangul.substring(i - 4, i);

for (k = str[j].length; k > 0; k--) {
strTmp[k] = str[j].substring(k - 1, k) ? str[j].substring(k - 1, k) : "";
strTmp[k] = han1[parseInt(strTmp[k])];

if (strTmp[k]) {
strTmp[k] += han3[str[j].length - k];
}

str2 = strTmp[k] + str2;
}

str[j] = str2;

if (str[j]) {
result = str[j] + han2[j] + result;
}

// 4자리마다 한칸씩 띄고 보여준다.
//result = (str[j])? " "+str[j]+han2[j]+result : " " + result;
j++;
str2 = "";
}

return pm + result;
};

설명

숫자를 파라미터로 보내 사용하면 변환된 한글 숫자가 리턴된다. 출처는 소스상에 남겼다. 해당 스크립트를 문법에 맞게 조금 변경했다.