# charAt

/**
 * String.prototype.charAt(index)
 * 
 * index 위치에 해당하는 문자 반환
 */

 console.log('boseok'.charAt(0)); // b
 console.log('boseok'.charAt(1)); // o
 console.log('boseok'.charAt(2)); // s

# charCodeAt

/**
 * String.prototype.charCodeAt(index)
 * 
 * charAt과 유사하게, 해당 인덱스의 위치에 해당하는 문자의 UTF-16 코드를 반환
 */

 console.log("abc".charCodeAt(0)); //97
 console.log("abc".charCodeAt(1)); //98

# codePointAt

/**
 * String.prototype.codePointAt(index)
 * 
 * fromCodePoint와 반대되는 프로토타입 메소드
 */

var icons = '☃★♲';

console.log(icons.codePointAt(1)); //9733

console.log(String.fromCodePoint(9733)); //★

# concat

/**
 * String.prototype.concat(...string)
 * 
 * 파라미터의 string과 this문자열을 합쳐서 새로운 문자열을 반환한다.
 */

console.log("bo".concat(',', 'seok')); //bo,seok
console.log("bo" + ',' + 'seok'); //bo,seok

# endsWith

/**
 * 
 * String.prototype.endsWith(string[, length])
 * this문자열이 파라미터의 string으로 끝나는지 true, false로 리턴.
 * this문자열의 길이를 두번째파라미터인 length로 제한할수도있음.(옵션)
 */

console.log('boseok!'.endsWith('!')); // true
console.log('boseok!'.endsWith('!', 4)); // false

# includes

/**
 * ES6 스펙
 * String.prototype.includes(searchString[, position])
 * 
 * this문자열에서 searchString이 포함되어있으면 true, 아니면 false 리턴.
 * 두번째파라미터는 옵션인데, position에 해당하는 index부터 찾는다.
 * 
 * 사실 이 메소드는 indexOf로 대체가 가능하긴하다.
 * 이 메소드가 나온이유를 추측해보면 당연히 편리성이다.
 * 
 * 예를들면 아래와 같은 코드를 보자.
 * 
 * const isIncludes = 'boseok'.indexOf('b');
 * if(isIncludes) {
 *  console.log('문자열 찾음');
 * } else {
 *  console.log('문자열 없음');
 * }
 * 
 * 헷갈리쥬?
 * 문자열을 찾았는데 해당 인덱스가 0이라서, if가 true가 아니고, false에 해당하므로
 * 문자열이 없다고 콘솔에 찍히는데, 이런 사소한 실수를 범할수있기때문에, includes가 나온것이 아닌가..ㅎㅎ
 * 
 * if에 -1같은걸 비교하는 로직이 들어가면 가독성이 살짝 불편해질수도있다.
 * 그래서 ES6환경에서는 includes를 선호한다. 
 */

 console.log('boseok'.includes('b'));
 console.log('boseok'.includes('b', 1));

# indexOf

/**
 * 
 * String.prototype.indexOf(searchString[, fromIndex])
 * 
 * this문자열에서 첫번째로 나타나는 searchString문자열을 찾고, 그 위치를 반환한다. 
 * fromIndex옵션은 어디서부터 찾을지 위치를 정할수있다.
 * 
 * 문자열이 없으면 -1 리턴
 */

console.log('boseok'.indexOf('b')); //0
console.log('boseok'.indexOf('b', 1)); //-1

# lastIndexOf


/**
 * 
 * String.prototype.lastIndexOf(searchValue[, fromIndex])
 * 
 * indexOf와 유사하지만 뒤에서부터 찾는다는 점에서 다르다.
 * this문자열에서 마지막 searchString문자열을 찾고, 그 위치를 반환한다.
 * fromIndex옵션은 어디서부터 찾을지 위치를 정할수있다.
 * 
 * 문자열이 없으면 -1 리턴
 */

console.log('boseokb'.lastIndexOf('b')); // 6

# length

/**
 * length 프로퍼티는 해당 문자열의 길이
 */
console.log("abcd".length); //4
const boseok = "boseok";
for (let i = 0; i < boseok.length; i++) {
  console.log(boseok[i]);
}

# localeCompare

/**
 * String.prototype.localeCompare(string)
 * 
 * 문자열끼리 비교하는데, 문자열을 순서대로 비교하여 같으면 0을 리턴,
 * 뒤에있으면 양수, 앞에있으면 음수를 리턴한다.
 * 앞, 뒤의 기준이 명확하진않지만 UTF-16기준인듯하다.
 * 
 * 사실 두번째, 세번째 파라미터도 있지만 내용이 많고 헷갈리기쉽다.
 * 공식문서를 참고할것
 * 
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
 */

var a = 'réservé';
var b = 'RESERVE';
var c = 'reserve';
var d = 'reserve';

console.log(a.localeCompare(b)); //1
console.log(c.localeCompare(b)); //-1
console.log(d.localeCompare(b)); //0

# match

/**
 * String.prototype.match(regex)
 * 
 * 파라미터는 정규식이다.
 * new RegExp() 를 넣어도 되고, /정규식/g 이런식으로 넣어도 된다.
 * /ab+c/i;
 * new RegExp('ab+c', 'i');
 * 같은 결과를 나타낸다. 
 * ES6 에서는 new RegExp(/ab+c/, 'i'); 이렇게도 사용할수있다.
 * 두가지 방법이 있는이유는 생성자 방식은 어떤패턴을 사용할지 정확히 알수없는경우- 사용자입력 등으로 생성되어서, 런타임방식으로 컴파일되게 한다.
 * g라는 위치는 정규식을 문자로 나타냈을때의 flag인데,
 * 아래의 의미를 나타낸다. /식/gi 이런식으로 이어서쓴다.
g
global match; 일치하는 첫 번째 문자에서 멈추지 않고 전체에서 일치하는 모든 문자를 검색합니다.
i
ignore case(대소문자를 구별하지 않습니다.)
m
multiline; 시작 혹은 끝 문자 탐색(^ and $)이 다중행에 적용되도록 합니다.  (예로,  \n 혹은 \r로 개행된 각각의 라인 시작 혹은 끝 뿐만 아니라, 전체 입력 문자의 시작 혹은 끝에서 일치합니다.
y 
sticky; matches only from the index indicated by the lastIndex property of this regular expression in the target string (and does not attempt to match from any later indexes).

 * 이 메소드를 이해하려면 정규식에 대한 이해가 먼저 필요하다.
 * 
 * 문자열에 패턴이 매칭되면 배열에 일치하는 값을 담아서 리턴해준다.
 * 일치하는 문자열이 없으면 null을 반환한다.
 */


if('boseokA'.match(/[A-Z]/gim)){
  console.log('matched');
} else {
  console.log('not matched');
}





# padEnd

/**
 * ES2017 스펙
 * 
 * String.prototype.padEnd(int, string)
 * 
 * 문자열에서 int-문자열길이만큼 string을 뒤에 붙여서 리턴한다.
 * string이 주어지지않았다면 ' '로 표기된다.
 */

const str = '100';
console.log(str.padEnd(4), ','); //'100,'
console.log(str.padEnd(4)); //'100 '
console.log(str.padEnd(2)); //'100'
console.log(str.padEnd(0)); //'100'
console.log(str.padEnd(-1)); //'100'

# padStart

/**
 * 
 * String.prototype.padStart(int, string)
 * padEnd와 같은건데, string을 앞에 붙인다는점에서만 다르다.
 * 
 */
const str1 = '5';

console.log(str1.padStart(2, '0')); //'05'

# repeat

/**
 * ES6 스펙
 * String.prototype.repeat(int)
 * 
 * this문자열을 int번만큼 반복한 문자열을 리턴한다
 */

 console.log('boseok'.repeat(5)); //'boseokboseokboseokboseokboseok'

# replace

/**
 * String.prototype.replace(string|regex, string|function)
 * 
 * 첫번째 파라미터에 regex와 string을 넣는것의 활용차이는 this문자열에서 매칭되는 모든 문자열을 바꿀것인가 이다.
 * 정규식의 flag에 g옵션으로 replace하면 replaceAll과 같다.
 * 문자열을 넣으면 매칭되는 첫번째문자열만 바꿔치기한다.
 * 
 * 두번째파라미터의 function을 넣을수도있다.
 * 
 * 파라미터로는 순서대로 (찾는 문자열, 찾은 인덱스, 원래 문자열)이 넘어온다.
 * 여러번 찾으면 콜백이 여러번 실행된다. 두번째파라미터인 찾은 인덱스만 바뀜.
 */

console.log('boseok'.replace('boseok', '123')); //123
console.log('boseok'.replace('o', '123')); //b123seok
console.log('boseok'.replace(/o/g, '123')); //b123se123k
console.log('boseok'.replace(/o/g, (...a) => {
  console.log(a); //[ 'o', 1, 'boseok' ] and [ 'o', 4, 'boseok' ]
  return '123';
}));  //b123se123k

# search

/**
 * String.prototype.search(regex)
 * 
 * this문자열에서 정규식에 일치하는 첫번째 문자열을 찾아서 그 위치를 반환한다.
 * 못찾으면 -1 리턴
 * 
 * indexOf와 거의 같지만 정규식으로 찾는다는점에서 다르다.
 */

 console.log('boseok'.search(/o/)); //1

# slice

/**
 * String.prototype.slice(beginIndex[, endIndex])
 * 
 * this문자열을 잘라서 리턴한다.
 * beginIndex가 this문자열길이 이상이면 빈문자열을 리턴한다.
 * 만약 음수를 넣는다면 this.문자열의 길이 -음수로 처리한다.
 * 양수를 넣으면 그 인덱스부터 끝까지의 문자열을 리턴한다.
 * 두번째파라미터를 넣는경우 어디까지 자를것인지 정할수있다.
 */

 const boseok = 'boseok';
 console.log(boseok.slice(-1)); //'k'
 console.log(boseok.slice(1)); //'oseok'
 console.log(boseok.slice(1, 3)); //'os'
 console.log(boseok.slice(6)); //''

# split

/**
 * String.prototype.split(string[, limit])
 * 
 * this문자열을 첫번째파라미터인 string으로 각각 잘라서 배열로 리턴한다.
 * 두번째 파라미터인 limit은 잘라진 배열의 길이를 제한할 수 있습니다.
 */
 console.log('boseok'.split('')); //[ 'b', 'o', 's', 'e', 'o', 'k' ]
 /**
  * 위의 예제에서 문자열을 간단하게 배열로 변경했습니다.
  * 하지만 이 방법은 좋지않습니다. UTF-16 codeunit기준으로 자르기때문이지요.
  * 아래의 끔찍한 결과를 확인해보시져!
  */
  console.log('𨭎'.split('')); //[ '�', '�' ]

/**
 *   아래의 방법들이 더 적절합니다.
 *  4개의 결과 모두 콘솔에 [ '𨭎', '1' ] 이 나올것입니다.
 * 제일 마지막 방법은 babel에 의해 트랜스파일링된 것입니다.
 */
 console.log(Array.from('𨭎1'));
 console.log([...'𨭎1']);
 console.log('𨭎1'.split(/(?=[\s\S])/u));
 console.log('𨭎1'.split(/(?=(?:[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))/));

# startWith

/**
 * 
 * String.prototype.startWith(string[, position])
 * 
 * this문자열이 첫번째파라미터로 주어진 string으로 시작하는지 판단해줍니다.
 * true, false리턴.
 * 
 * position은 옵션인데, 주어지지않으면 0으로 시작하고, 주어지면
 * 해당하는 인덱스부터 찾기 시작합니다.
 */

console.log('boseok'.startsWith('b')); //true
console.log('boseok'.startsWith('bo')); //true
console.log('boseok'.startsWith('o')); //false
console.log('boseok'.startsWith('o', 1)); //true

# static_fromCharCode

/**
 * String.fromCharCode(...number)
 * 
 * UTF-16 포맷에 해당하는 문자열을 리턴
 * 
 * 문자 하나를 UTF 16으로 변환하는것은 'a'.charCodeAt(0) 이런식으로 사용하면 된다.
 */

console.log(String.fromCharCode(97)); // a
console.log(String.fromCharCode(43)); // +

# static_fromCodePoint

/**
 * fromCharCode 와 비슷하게, 해당 number에 해당하는 특수문자를 반환.
 * String.fromCodePoint(...number)
 */

 console.log(String.fromCodePoint(9733)); // ★

# substring

/**
 * String.prototype.substring(startIndex[, endIndex])
 * 우선 substr은 deprecated입니다. 대신에 이 메소드를 사용하세요.
 * 기본적인 사용방법은 slice와 동일합니다.
 * 대신에 startIndex가 endIndex보다 크면 내부적으로 startIndex와 endIndex를 swap합니다. (slice는 그렇지않음)
 * 그리고 음수를 넣으면 차이점이 보입니다.
 */
console.log('boseok'.substring(0, 1)); //'b'
console.log('boseok'.substring(0)); //'boseok'

console.log('boseok'.substring(-1)); //'boseok'
console.log('boseok'.slice(-1)); //'k'
console.log('boseok'.substring(1, 0)); //'b'
console.log('boseok'.slice(1, 0)); //''


# toLocaleLowerCase

/**
 * String.prototype.toLocaleLowerCase(option)
 * 
 * this 문자열을 모두 소문자로 바꿔서 리턴합니다.
 * option파라미터로 locale을 정할수있는데, 여러개의 locale을 넣는다면, 
 * best locale을 자동으로 선택한다고하네요.
 * 기본 locale은 해당호스트의 locale입니다.
 */

 console.log('BOSEOK'.toLocaleLowerCase('us')); //'boseok'

# toLocaleUpperCase

/**
 * String.prototype.toLocaleUpperCase()
 * this 문자열을 모두 대문자로 바꿔서 리턴합니다.
 * option은 toLocaleLowerCase와 같습니다.
 */

console.log('boseok'.toLocaleUpperCase('us')); //'BOSEOK'

# toLowerCase

/**
 * String.prototype.toLowerCase()
 * 
 * this문자열을 모두 소문자로 바꿔서 만들어진 문자열을 리턴합니다.
 */

 console.log('BOSEOK'.toLowerCase()); //'boseok'

# toString

/**
 * String.prototype.toString()
 * 
 * 
 */
const v1 = 'boseok'.toString();
const v2 = '123'.toString();
console.log(typeof v1, v1); //string 'boseok'
console.log(typeof v2, v2); //string '123'

var x = new String('BOSEOK');
console.log(typeof x, x.toString()); //object 'BOSEOK'

# toUpperCase

/**
 * String.prototype.toUpperCase()
 * 
 * this문자열을 모두 소문자로 바꿔서 만들어진 문자열을 리턴합니다.
 */

console.log('boseok'.toUpperCase()); //'BOSEOK'

# trim

/**
 * String.prototype.trim()
 * 
 * this문자열의 양끝(시작과 끝)에서 공백을 제거하고 새롭게 만들어진 문자열을 리턴합니다.
 * 유사한 trimRight, trimLeft도 있습니다. 
 * trimStart, trimEnd도 있지만 node.js에서는 동작하지않습니다.
 */

 console.log('    boseok  '.trim()) //'boseok'
 console.log('    boseok  '.trimRight()) //'    boseok'
 console.log('    boseok  '.trimLeft()) //'boseok  '

# valueOf

/**
 * String.prototype.valueOf()
 * 
 * toString과 같습니다. 주로 js내부적으로 사용하기위해 만들어졌습니다.
 */

 const v1 = '123';
 console.log(typeof v1.toString());
 console.log(typeof v1.valueOf());