codeSpitz
코드스피츠89 - Programming 101 4회차

변수, 제어문, 함수, 클래스 등 언어의 기초를 이루는 구성과 상세하고 미묘한 사용법을 배웁니다.


알고리즘과 순수 데이터를 분리해라

  • 내가 갖고 있는 데이터의 구조가 로직을 너무 많이 가지고 있으면 코드를 분리해라.
  • 순수하게 데이터만 다루는 알고리즘과 부가적인 일을 하는 알고리즘을 나누어라
    • N차원 배열을 스택 형태로 저장하는 알고리즘
    • 배열의 원소들을 문자열로 변환하는 알고리즘

변수의 라이프 사이클은 코드의 형태와 일치하는 것은 아니다

  • 매개변수로 객체를 전달하는 경우 해당 객체는 함수내부에서 참조하여 변경할 수 있게 된다.
  • 함수내부에서 객체를 변경할 수 있다보니, 처음에 설계했던것고 다르게 객체를 조작하게 될 수도 있다.
  • 원하는 의도에 맞게 매개변수를 설정해야한다. -> 함수를 재귀적으로 호출할 때 매번 얕은복사를 해서 전달할것이냐, 아니면 같은 객체를 전달할것이냐?

if else의 일반화

  • if else 제어문 내부에는 같은 제어레벨을 가진 코드를 작성해야하고, 그게 가능해지면 일반화된 라우팅 테이블을 작성할 수 있게된다. [56:30]
  • 원래 분기해야할 경우의 수만큼 전략객체를 만들고, 기준 상태를 판정하여 적합한 전략객체를 매핑하는 매퍼 == 라우터

과제 구현 코드

  • diff 보기 (opens in a new tab)
  • 중첩된 배열과 객체를 파싱하는 부분을 수정했다. 하지만 여기서 권장하는 재귀->while변환하는 부분을 구현하지 못했다...
// JSON.stringify를 구현하시오
// https://www.youtube.com/watch?v=rQOpmgo99BQ
 
/**
 * 자료
 * https://reference.codeproject.com/Book/javascript/reference/global_objects/json/stringify
 * https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
 */
 
const parsingRouter = {
	'string': (v) => `"${v.toString()}"`,
	'number': (v) => v.toString(),
	'null': () => 'null',
	'undefined': (_, valueOwnerConstructor) => valueOwnerConstructor === Array ? 'null' : undefined,
	'function': (_) => 'null',
	'symbol': (_, valueOwnerConstructor) => valueOwnerConstructor === Array ? 'null' : undefined,
	'boolean': (v) => v.toString(),
	'array': (arr, valueOwnerConstructor) => {
		// 재귀를 while문으로 변경해야함..
		let _str = "";
		let acc = "";
		if (arr.length) {
			for (let item of arr) {
				const parsed = myJSON.valueToString(item, valueOwnerConstructor);
				_str += "," + parsed;
			}
			acc = _str.substr(1);
		}
		return `[${acc}]`
	},
	'object': (obj, valueOwnerConstructor) => {
		let _str = "";
		let acc = "";
		if (Object.keys(obj).length) {
			for (let item in obj) {
				const parsedValue = myJSON.valueToString(obj[item], valueOwnerConstructor);
				const parsedKey = myJSON.valueToString(item, valueOwnerConstructor);
				_str += "," + `${parsedKey}:${parsedValue}`;
			}
			acc = _str.substr(1);
		}
		return `{${acc}}`
	},
};
 
const valueRouter = {
	'null': () => 'null',
	'undefined': () => undefined,
	'object': (v, valueOwnerConstructor) => myJSON.valueToString(v, valueOwnerConstructor),
	'array': (v, valueOwnerConstructor) => myJSON.valueToString(v, valueOwnerConstructor),
	'boolean': (v) => myJSON.valueToString(v, null),
	'symbol': (v) => myJSON.valueToString(v, null),
	'function': (v) => myJSON.valueToString(v, null),
	'number': (v) => myJSON.valueToString(v, null),
	'string': (v) => myJSON.valueToString(v, null),
}
 
class myJSON {
	constructor() {
 
	}
 
	static getType(value) {
		if (value === null) {
			return ('null');
		} else if (value === undefined) {
			return ('undefined');
		} else {
			let jsType = typeof value;
			return (jsType === 'object'
				? Array.isArray(value)
					? 'array'
					: 'object'
				: jsType);
		}
	}
 
	static valueToString(value, valueOwnerConstructor) {
		const valueType = myJSON.getType(value);
		let str = parsingRouter[valueType](value, valueOwnerConstructor);
 
		return str;
	}
	static wrapStr(start, end, str) {
		return `${start}${str.join(',')}${end}`;
	}
 
	static stringify(value) {
		const valueType = myJSON.getType(value);
		return valueRouter[valueType](value, value ? value.constructor : null);
	}
}
 
const test01 = {
	str: 'a',
	num: 1,
	'undefined': undefined,
	'null': null,
	symbol: Symbol('test'),
	boolean: true,
}
 
const tests = [];
tests.push({})
tests.push(1)
tests.push(null)
tests.push('foo')
tests.push([1, '1', true, null, undefined, Symbol(''), () => ''])
tests.push([])
tests.push([1, 2, ["a", [1, 2], false], 3, ["b", "c", [1, 2]]])
tests.push([1, 2, [], 3, ["b", "c", [1, 2]]])
tests.push({a: 1, b:2, c:[], d:3, e:{b: "b", c:"c", d:[1, 2]}, f: {}})
tests.push([[[]]])
tests.push({a:{b:{c:{}}}})
// tests.push([{}])
// tests.push({a: {}})
 
function testMyJSON(v) {
	try {
		console.log(`==== real value ====`);
		console.log(v)
		console.log(`==== myJSON() ====`)
		console.log(myJSON.stringify(v))
		console.log(`==== JSON() ====`)
		console.log(JSON.stringify(v))
		console.log(`==== RESULT ====`)
		console.log(myJSON.stringify(v) === JSON.stringify(v))
		console.log("\n")
	} catch (e) {
		console.error(e)
	}
 
}
 
tests.map(test => testMyJSON(test))