8월 첫째 주 TWIL

sgyoon·2019년 8월 23일
0

TWIL

목록 보기
2/32
post-thumbnail

JavaScript

1. Object

Object.assign()

열거할 수 있는 하나 이상의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용합니다. 대상 객체를 반환합니다.
[ Object.assign() | MDN ]

let obj1 = {
  a: 1,
  b: 2
};
let obj2 = {
  b: 4,
  c: 3
};

object.assign(obj1, obj2); // 타겟 obj1 -> obj1이 변한다.
// {a: 1, b: 4, c: 3}
obj1
// {a: 1, b: 4, c: 3}

Object.assign({}, obj1, obj2); // 타겟 {} -> 클론이 만들어진다.
// {a: 1, b: 4, c: 3}
obj1 // 변하지 않음.
// {a: 1, b: 2}

let newObj = Object.assign({}, obj1, obj2);
newObj
// {a: 1, b: 4, c: 3}
Object.assign(newObj, obj1); // 타겟과 출처가 같은 키를 가졌다면, 출처의 값이 타겟의 값을 덮어쓴다.
// {a: 1, b: 2, c: 3}

2. Array

Array 메서드의 Mutating

기존 배열을 변경하는 대표적인 Array 메서드들

메서드명반환내용
Array.push()push() 메서드는 배열의 끝에 하나 이상의 요소를 추가하고, 배열의 새로운 길이를 반환합니다.
Array.ushift()unshift() 메서드는 새로운 요소를 배열의 맨 앞쪽에 추가하고, 새로운 길이를 반환합니다.
Array.pop()pop() 메서드는 배열에서 마지막 요소를 제거하고 그 요소를 반환합니다.
Array.shift()shift() 메서드는 배열에서 첫 번째 요소를 제거하고, 제거된 요소를 반환합니다.
Array.splice()splice() 메서드는 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가합니다.제거한 요소를 담은 배열을 반환합니다.

Array.reduce()

배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.
초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용합니다. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생합니다.
[ Array.prototype.reduce() | MDN ]

// 인덱스에 배열이 들어있는 배열 arr을 하나의 배열로 만들기
function joinArrayOfArrays(arr) {
  const joinedArr = arr.reduce(function(acc, val) {
    return acc.concat(val);
  });
  return joinedArr;
}
// 배열 안에서 가장 길이가 짧은 값을 찾기
return newArray.reduce(function(arr, curr) {
  if (arr.length <= curr.length) {
    return arr;
  } else {
    return curr;
  }
});
// 배열 안 모든 요소를 곱한 값을 구하기
function allElements(arr) {
  return arr.reduce(function(acc, val) {
    return acc * val;
  });
}

Array.filter()

주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.
[ Array.prototype.filter() | MDN ]

// 100보다 작은 값만 반환하기
return prop.filter(function(el) {
  return el < 100;
});
// null값이 아닌 값만을 반환하기
var finalAnswer = answer.filter (
    function (answer) {
      return answer != null;
  }
);

Array.map()

배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.
[ Array.prototype.map() | MDN ]

var array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x * 2);
console.log(map1);
// [2, 8, 18, 32]

// 배열 각 요소를 거듭제곱한 값을 반환함
return prop.map(function(x) {
    return Math.pow(x, 2);
  });

const map = prop.map(x => x * x);

console.log(map);
// [1, 16, 81, 256]

Array.slice()

어떤 배열의 begin부터 end까지(end 미포함)에 대한 얕은 복사본을 새로운 배열 객체로 반환합니다.
[ Array.prototype.slice() | MDN ]

var animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];

console.log(animals.slice(0, -1));
// ["ant", "bison", "camel", "duck"]
animals.slice(); // 추출시점(인덱스값)을 넣지 않으면 클론이 생성된다.

Array.push()

배열의 끝에 하나 이상의 요소를 추가합니다.
값 한 개 뿐 만 아니라 배열 혹은 여러개의 값을 만들거나 넣을 수 있습니다.
[ Array.prototype.push() | MDN ]

function convertObjectToList(obj) {
  let result = [];
  for (let key in obj) {
    result.push(key, obj[key]); // 여러개의 값을 넣을 수 있다.
  }
  return result;
}
function convertObjectToList(obj) {
  let result = [];
  for (let key in obj) {
    result.push([key, obj[key]]); // 값을 배열로 만들어 넣을 수 있다.
  }
  return result;
}
function convertObjectToList(obj) {
  let result = [];
  for (let key in obj) {
    result.push({key : obj[key]}); // 값을 객체 형태로 넣으려고 시도했다. 키값은 모두 'key'로, value값은 값으로 전달된다. 'key'를 적으면 value로 key가 전달된다.
  }
  return result;
}
// [{key: "Holly"}, {key: 35}, {key: "producer"}]

Array.indexOf()

배열에서 지정된 요소를 찾을 수 있는 첫 번째 인덱스를 반환합니다. 존재하지 않으면 -1을 반환합니다.
[ Array.prototype.indexOf() | MDN ]

var beasts = ['ant', 'bison', 'camel', 'duck', 'bison'];

console.log(beasts.indexOf('bison'));
// expected output: 1

// start from index 2
console.log(beasts.indexOf('bison', 2));
// expected output: 4

console.log(beasts.indexOf('giraffe'));
// expected output: -1

Array.isArray()

인자가 Array인지 판별합니다. 객체가 Array라면 true, 아니라면 false를 반환합니다.
[ Array.isArray() | MDN ]

const emptyArray = [];
const filledArray = [1, 2, 3];
const obj = {};

// 매개변수가 배열인지 아닌지를 검사하기
if(Array.isArray(emptyArray)) {
  console.log('hello');
};
// 'hello'

if(Array.isArray(obj)) {
  console.log('hello');
};
// undefined
// 배열이 비었는지 아닌지를 검사하기 
if(emptyArray.length === 0) {
  console.log('hello');
};
// 'hello'

if(filledArray.length === 0) {
  console.log('hello');
};
// undefined

3. String

String.concat()

호출 문자열에 매개변수 문자열을 이어 붙인 결과를 반환합니다. 원본 문자열과 결과 문자열의 변형은 서로에게 영향을 미치지 않습니다. 매개변수의 값이 문자열이 아니면 계산 전에 문자열로 변환합니다.
[ String.prototype.concat() | MDN ]

str1.concat(str2, str3);

var str1 = 'Hello';
var str2 = 'World';

console.log(str1.concat(' ', str2)); // ' ' 삽입
// expected output: "Hello World"

console.log(str2.concat(', ', str1)); // ', ' 삽입
// expected output: "World, Hello"

String.toUpperCase(), String.toLowerCase()

var sentence = 'The quick brown fox jumps over the lazy dog.';

// 문자열을 대문자로 변환해 반환합니다.
sentence = sentence.toUpperCase();
// 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.'

// 문자열을 소문자로 변환해 반환합니다.
sentence = sentence.toLowerCase();
// 'The quick brown fox jumps over the lazy dog.'

4. 문자열이 아닌 값을 문자열로 변환하는 메서드

String()

일반적으로 toString() 함수를 많이 사용하고 있지만, toString()의 "안전한" 대안으로 String을 사용할 수 있습니다. String은 [null]과 [undefined]에 대해서도 잘 동작합니다.
[ 문자열 변환 | MDN ]

var outputStrings = [];
for (var i = 0, n = inputValues.length; i < n; ++i) {
  outputStrings.push(String(inputValues[i]));
}

Number.toString()

toString() 메소드는 메소드의 첫 번째 아규먼트를 파싱하여, 메소드는 특정 기수(radix)를 기준으로 한 진수 값의 문자열을 환원하기 위한 시도를 합니다. 진수를 나타내는 기수 값(radix) 이 10 이상의 값일 때는, 알파벳의 글자는 9보다 큰 수를 나타냅니다. 예를 들면, 16진수(base 16)는, 알파벳 f 까지 사용하여 표현됩니다.
만약에 radix값 이 지정되지 않으면, 임의로 10진수로 가정하게 됩니다.
[ Number.prototype.toString() | MDN ]

var count = 10;

console.log(count.toString());    // '10'
console.log((17).toString());     // '17'
console.log((17.2).toString());   // '17.2'

var x = 6;

console.log(x.toString(2));       // '110' 2진수
console.log((254).toString(16));  // 'fe' 16진수

console.log((-10).toString(2));   // '-1010' 10진수 음수를 2진수로
console.log((-0xff).toString(2)); // '-11111111' 16진수 음수를 2진수로

Object.toString()

모든 객체에는 객체가 텍스트 값으로 표시되거나 객체가 문자열이 예상되는 방식으로 참조 될 때 자동으로 호출되는 toString() 메서드가 있습니다. 기본적으로 toString() 메서드는 Object에서 비롯된 모든 객체에 상속됩니다.
[ Object.prototype.toString() | MDN ]

function Dog(name, age) {
  this.name = name;
  this.age = age;
}

var dog1 = new Dog('Gabby', '24');

Dog.prototype.toString = function dogToString() { // toString 메서드를 재정의함
  return '' + this.name + ' ' + this.age;
}

console.log(dog1.toString()); // 재정의한 메서드의 반환 결과
// "Gabby  24"

이 메서드가 사용자 지정 개체에서 재정의되지 않으면 toString()은 "[object type]"을 반환합니다. 여기서 type은 object type입니다.

var o = new Object(); // 재정의 하지 않았을 때
o.toString(); // returns [object Object]

5. Math 메서드 + 숫자열을 반환하는 함수

Math.abs()

주어진 숫자의 절대값을 반환합니다.
[ Math.abs() | MDN ]

Math.abs('-1');     // 1
Math.abs(-2);       // 2
Math.abs(null);     // 0
Math.abs('');       // 0
Math.abs([]);       // 0
Math.abs([2]);      // 2
Math.abs([1,2]);    // NaN
Math.abs({});       // NaN
Math.abs('string'); // NaN
Math.abs();         // NaN

Math.sqrt()

숫자의 제곱근을 반환합니다.
[ Math.sqrt() | MDN ]

Math.sqrt(9); // 3
Math.sqrt(2); // 1.414213562373095

Math.sqrt(1);  // 1
Math.sqrt(0);  // 0
Math.sqrt(-1); // NaN

parseInt()

문자열 인자의 구문을 분석해 특정 진수(수의 진법 체계에 기준이 되는 값)의 정수를 반환합니다.
[ parseInt() | MDN ]

만약 radix 가 undefined 이거나 0이라면, (또는 없다면), JavaScript 는 아래와 같이 임의 처리합니다.

  • 인풋 값 string 이 "0x" 나 "0X"로 시작한다면, radix 는 16(16진)이며, 나머지 문자열은 파싱됩니다.
  • 인풋 값 string 이 "0"으로 시작한다면, radix 는 8(8진)이거나, 10(십진)입니다. 정확히 이 선택된 radix 는 구현 의존적적입니다. ECMAScript 5 는 10(십진)이 사용되는 것을 명시하지만, 모든 브라우저가 아직 이렇게 되지 않습니다. 이러한 이유로 항상 parseInt를 사용할 때는 radix 값을 명시해야 합니다.
  • 인풋 값 string 이 다른 값으로 시작 된다면, radix 는 10(십진)입니다.
// 다음의 예제는 모두 15을 리턴합니다.
parseInt("15.3456");
parseInt("15.3456", 10);
parseInt("15,123", 10);
parseInt("1111", 2);
parseInt("17", 8);
// 다음의 예제는 모두 -15을 리턴합니다.
parseInt("-15", 10);
parseInt("-1111", 2);
parseInt("-17", 8);
  • 만약 매개변수 string이 문자열이 아니면 문자열로 변환(ToString 추상 연산을 사용)합니다.
let a = 3.11
let b = 4.13

parseInt(a + b);
// 7

parseFloat()

[ parseFloat() | MDN ]

// 아래 예제는 모두 3.14를 반환합니다.
parseFloat(3.14);
parseFloat('3.14');
parseFloat('3.14와 숫자가 아닌 문자들');

6. 양수를 음수로, 음수를 양수로 만드는 방법

0 - n // -n
-1 * n // -n

7. 의문점 해결 : 객체와 let의 특징

Q. 사원들의 정보를 다른 형태로 변형 할 수 있는 함수 "transformEmployeeData" 함수를 작성하세요.
A1.

// 예시 인자
var array = [
  [['firstName', 'Joe'], ['lastName', 'Blow'], ['age', 42], ['role', 'clerk']],
  [['firstName', 'Mary'], ['lastName', 'Jenkins'], ['age', 36],['role', 'manager']]
];

// 원하는 반환 결과
[
  { firstName: 'Joe', lastName: 'Blow', age: 42, role: 'clerk' },
  { firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager' }
];
// 함수
function transformEmployeeData(array) {
  let result = [];

  for (let i = 0; i < array.length; i++) {
    let arrInArr = array[i];
    let obj = {};
    for (let j = 0; j < arrInArr.length; j++) {
      obj[arrInArr[j][0]] = arrInArr[j][1];
    }
    result.push(obj); // obj를 두 번 result에 push해준다.
  }

  return result;
}

이 문제를 페어 프로그래밍으로 풀다가 의문이 생겼다. 객체 obj를 첫번째 for문 안쪽이 아닌 바깥쪽에 선언해주면 어떤 방식으로 에러가 나는지를 살펴보았더니, 마지막에 대입되는 객체만 result에 두 번 push되어 있었다. 그런데 그 이유를 잘 이해할 수 없었다.

A2.

function transformEmployeeData(array) {
  let result = [];
  let obj = {}; // 여기에 obj를 선언함
  for (let i = 0; i < array.length; i++) {
    let arrInArr = array[i];
    for (let j = 0; j < arrInArr.length; j++) {
      obj[arrInArr[j][0]] = arrInArr[j][1];
    }
    result.push(obj);
  }
  return result;
}
// 결과 : for문이 만들어내는 마지막 객체만 두 번 result에 push 되어있다.
[
  { firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager' }
  { firstName: 'Mary', lastName: 'Jenkins', age: 36, role: 'manager' }
];

그래서 개발자 도구로 중단점을 이용해 A2를 살펴보니 다음과 같았다.

  1. 첫번째 for문에서 i = 0일 때, { firstName: 'Joe', lastName: 'Blow', age: 42, role: 'clerk' } 가 obj에 대입되고 result에 push된다.
  2. 첫번째 for문에서 i = 1일 때, for문이 실행되면서 동시에 obj가 두 번째 배열을 읽은 값인 Mary로 바뀐다.
  3. 동시에 result안에 push된 obj안에도 반영되어, 결국 result의 0번째 인덱스값인 객체 obj의 내용이 Mary로 바뀐다.
  4. 그 후 Mary의 키와 값이 대입된 객체 obj가 result에 push되어 result의 1번 인덱스에 들어간다.
  5. 결과적으로 result 의 0번과 1번 인덱스 모두 Mary가 된다.

정리하면 :

  • A2의 경우, result 안에 push된 obj가 맨 처음에 선언한 obj와 같기 때문에, 처음에 선언한 obj가 변하면 result안의 obj도 변한다.
  • A1의 경우, 첫 for문 안쪽에 obj를 새로 선언하면, for문이 반복될 때마다 for문 안쪽은 새로운 블록이 되기 때문에, i = 0일 때 선언된 obj와 i = 1일 때 선언된 obj는 서로 다른 변수이므로 서로 영향을 미치지 않는다.

2019.08.02 티스토리 블로그에 작성한 글을 velog로 옮김

profile
👩🏻‍💻

0개의 댓글