112 posts tagged with "javascript"
Any application that can be written in JavaScript, will eventually be written in JavaScript
View All TagsJSON.parse unexpected type Error
database 에 이미 json 으로 저장된 데이터를 가져와 JSON.parse 메소드로 JSON 데이터를 파싱하는 중에 값이 string 인데도 오류가 나는 경우가 있다.
로그를 확인해보면
{"data":"[{"name":"gracefullight"},{"name","daniel"}]"}
[] 배열 기호 앞뒤로 따움표가 들어가 있다. 이중 object 가 있다면 선언문 앞뒤로 따움표가 들어가 파싱 오류가 난다.
원인
jQuery.ajax 의 dataType 을 json 으로 설정해 데이터를 받는데, 이미 json 형태의 string 이 넘어와 두번 치환이 된 것 같다.
다시 json 을 인식할 수 있게 치환해보자
소스
const jsonReplace = function (j) {
if (j) {
j = j
.replace(/"\[/g, "[")
.replace(/\]"/g, "]")
.replace(/"\{/g, "{")
.replace(/\}"/g, "}");
}
return j;
};
설명
해당 함수로 오류가 나는 json string 을 치환 후에 다시 JSON.parse 를 실행하면 된다.
여담
정규식을 활용해 replace 중첩을 피하게 짤 수 있을 것 같은데...
hasOwnProperty vs prototype.hasOwnProperty
hasOwnProperty
for-in 구문을 쓸 때 상속된 프로퍼티나 this 구문을 방지하기 위하여 보통 hasOwnProperty 로 체크한다.
for (prop in obj) {
// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty(prop)) {
// code...
}
}
문제점
위와 같은 방식은 아래와 같이 hasOwnProperty 가 재정의 된 객체에서 오류를 발생할 수 있다.
소스
const obj = {
hasOwnProperty: function () {
return false;
},
data1: 1,
};
for (prop in obj) {
// obj.hasOwnProperty(prop) 의 결과는 항상 false
// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty(prop)) {
// 이 구문은 실행되지 않는다.
}
}
prototype.hasOwnProperty
따라서 prototype 을 사용해 코딩해야한다.
소스
for (prop in obj) {
// 첫번째 방법
if ({}.hasOwnProperty.call(obj, prop)) {
// 체크
}
// 두번째 방법
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
// 체크
}
}
설명
첫번째 방법은 익명 Object 를 생성한 후 obj 와 prop 을 밀어넣는 방식이고 두번째 방법은 기본 Object 의 hasOwnProperty 를 가져와 obj 와 prop 을 밀어넣는 방식이다.
두번째 방법이 새(익명) Object 를 생성하지 않기에 이 방법을 사용하면 된다.
더 자세하게 알고 싶다면 mdn을 참조한다.
Throttle, Debounce Pattern
javascript throttle 패턴과 debounce 패턴에 대해 알아보자.
Throttle
매 ms 마다 한 번만 호출된다. mousemove, scroll 같은 이벤트로 호출되는 함수는 이벤트 발생시 무한정 호출되어 성능 저하를 가지고 오는데, 이를 방지할 수 있다.
모바일에서 스크롤링 더보기에 사용할 수 있다.
소스
const throttleFunction = (function () {
"use strict";
const timeWindow = 500; // 여기에 시간(ms)을 지정한다
let lastExecution = new Date(new Date().getTime() - timeWindow);
// ES6 이하일 경우 ...args에 호출할 parameter 만큼 준다 function(arg1, arg2...)
const throttleFunction = function (...args) {
// 여기에 로직을 구현한다
};
return function () {
if (lastExecution.getTime() + timeWindow <= new Date().getTime()) {
lastExecution = new Date();
return throttleFunction.apply(this, arguments);
}
};
})();
// 사용법
throttleFunction(param1, param2);
Debounce
마지막 호출로부터 ms 후에 함수를 한번 호출한다. 지연된 호출을 할 수 있게 해주는데, 호출이 반복되는 동안은 실행을 방지하고, 호출이 멈춘 뒤 지정한 ms 후에 함수를 실행해 성능 저하를 막을 수 있다.