Skip to main content

[dB's 자바스크립트] 기초개념 정리 (Basic Concept)

Data structures and types 

Data types 
  • Boolean 
  • null 
  • undefined 
  • Number 
  • String 
  • Symbol 
  • Object

Object를 제외하고 나머지 6개의 데이터 타입은 원시형(primitives) 으로 객체와 메소드가 없으며 immutable 속성을 가지고 있습니다. undefined은 변수가 정의되어 있지만 아무 값도 할당 받지 않은 상태이며, null은 null값을 할당받은 것을 말합니다. 또 다른 차이점은 null은 객체타입, undefined은 undefined이 출력됩니다. 

Primitive wrapper objects 
원시타입형에서 properties에 값을 할당은 안되지만, 오류는 아닙니다. 이는 null과 undefined를 제외한, 나머지 원시값은 그 값들을 감싸는 primitive wrapper objects 때문입니다. 객체의 원시값을 가져올때는 valueOf() 사용가능합니다.

var fred = "Fred Flintstone";
fred.favoriteFood = "Brontosaurus Steak";

// Outputs: undefined
console.log(fred.favoriteFood);

// 문자열 표현
let str1 = new String('str1')
let str2 = 'str2'

typeof str1 // 'object'
typeof str2 // 'string'

str1 instanceof String // true
str2 instanceof String // false

str1 instanceof Object // true
str2 instanceof Object // false
NaN

typeof NaN === 'number' // true 

NaN === NaN    // false 
NaN !== NaN    // true 

isNaN(NaN)       // true 
isNaN(0)         // false 
isNaN('oops')    // true 
isNaN('0')       // false 

// 숫자 구별방법
function isNumber(value) {
  return typeof value === 'number' && isFinite(value);
}
Literals 
Array, Boolean, Floating-point, Integers, Object, RegExp, String

var coffees = ['French Roast', 'Colombian', 'Kona'];

var cats = [];
cats[30] = ['Dusty'];
console.log(cats.length); // 31
console.log(cats['length']); // 31
배열의 length를 이용하여 값을 제거할 수 있습니다.

var cats = ['Dusty', 'Misty', 'Twiggy'];
console.log(cats.length); // 3
cats.length = 2;
console.log(cats);
for 문과 forEach()를 사용해서 배열을 순환할 수 있습니다.

var colors = ['red', 'green', 'blue'];
for (var i = 0; i < colors.length; i++) {
  console.log(colors[i]);
}

var colors = ['red', 'green', 'blue'];
colors.forEach(color => console.log(color));
Array methods 아래 배열 매소드 중에서 자주 사용하는 것으로는
concat()-new, join(), push(), pop(), shift(), unshift(), slice()-new, splice(), sort(), indexOf(), lastIndexOf(), forEach(), map()-new, filter()-new, every()-true/false, some()-true/false, reduce(), reduceRight() 특정값이 있는지 찾을때는 indexOf()를 사용합니다. 매칭되는 첫 번째 포지션을 리턴하며 없을 경우 -1 을 리턴합니다.

var isExist = (array.indexOf(“특정값”)!== -1 )
filter를 사용해서 JSON 오브젝트로 이루어진 배열중에 특정 값만 필터 시킬때 사용합니다.

var arr = [    
  {"name":"apple", "count": 2},    
  {"name":"orange", "count": 5},    
  {"name":"pear", "count": 3},    
  {"name":"orange", "count": 16}
];    
var newArr = arr.filter(function(item){    
  return item.name === "orange";
});  
console.log("Filter results:",newArr);
for 루프대신 forEach()사용도 가능합니다.

var array = [1,2,3,4,5];
array.forEach( function( v, i ){
  if( v === 3 ){
    console.log( v + ":" + i); // 3:2 가 나온다.
  }
});
map은 루프에서 return 할 수 있다는 특징과 길이가 같은 배열로 결과를 리턴받고 싶을 때 사용합니다. reduce는 array를 하나의 값으로 리턴합니다.

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
배열은 정규표현식과 match의 결과값이기도 합니다.
RegExp.exec(), String.match(), and String.split().

유사배열 객체 (array-like objects) 
document.querySelectorAll(), document.getElementsByTagName()의 리턴값인 NodeList 또는 arguments는 배열처럼 생겼지만 모든 메소드를 사용할 수는 없습니다. 예를들어, arguments 객체는 length 속성을 제공하지만 forEach()를 사용할 수 없습니다. NodeList는 live collection 또는 static collection 입니다.

getElementsByClassName() : HTMLCollection & live
getElementsByTagName() : HTMLCollection & live
getElementsByName() : NodeList & live
querySelectorAll() : NodeList & not live

Iterators

iterable 프로토콜은 반복문을 가능케합니다. String, Array, TypedArray, Map, Set은 iterable이 내재되어 있습니다. @@iterator 메소드가 반드시 필요합니다. 객체에 iterator을 주입시키는 방법은 아래와 같습니다.

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};
[...myIterable]; // [1, 2, 3]
for...of / for...in for...in 은 객체의 enumerable 속성을 반복하며, for...of는 iterable 객체를 반복합니다. 첫번째 반복문에서는 0, 1, 2, "foo", "arrCustom", "objCustom"만 출력합니다. 배열안의 값인 3, 5, 7은 enumerable 속성이 아니기 때문입니다. 배열이 인덱스는 enumerable속성입니다.

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];
iterable.foo = 'hello';

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs 0, 1, 2, "foo"
  }
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}
enumerable은 간단히 말해 for...in 또는 Object.keys로 접근시 노출되는 것을 의미합니다. 아래 코드 실행시 enumerable의 값이 true로 나와 있습니다. 새로운 프로퍼티 생성시 이 값은 기본적으로 true로 설정되어 있기 때문입니다.

const obj = {
    purposeOfLife: 42,
}

Object.getOwnPropertyDescriptor(obj, 'purposeOfLife')

// result
{
    value: 42,
    writable: true,
    enumerable: true,
    configurable: true
}
defineProperty를 사용할 때 주의 할점은 기본값이 false입니다. non-enumerable properties를 생성하려면 Object.definedProperty()를 사용하시면 됩니다.

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
Object.keys(person); // ['age']

Functions

자바스크립트에서 함수는 First-Class-Object로 변수나 데이터 구조안에 담을 수 있으며 인자로 전달할 수 있고 반환값으로도 사용할 수 있습니다. 원시형타입과 달리 함수의 파라미터에 배열 또는 객체를 넘겨서 함수 안에서 값을 변경할 경우 기존의 값이 바뀝니다.

function myFunc(theObject) {
  theObject.make = 'Toyota';
}

var mycar = {make: 'Honda', model: 'Accord', year: 1998};
var x, y;

x = mycar.make; // x gets the value "Honda"

myFunc(mycar);
y = mycar.make; 
함수선언(function declarations)이 위의 예제와 같다면 함수 표현식(function expressions)은 아래와 같습니다. 함수 표현식을 사용할 경우, 익명함수로 작성이 가능합니다. 자기호출함수로 해석과 동시에 실행되는 코드블럭 생성이 가능하며 이는 재귀함수와는 다른 개념입니다.

var square = function(number) { return number * number; };
var x = square(4); // x gets the value 16

//named function expression
var foo = function foo() {
    console.log('hello');
};

// self invoking function expression
(function foo() {
    console.log('hello');
})();
함수 표현식은 호이스팅 되지않습니다.

a(); 
b(); 

function a(str){ 
    alert(str); 
} 
var b = function(str){ 
    alert(str); 
}
함수 스코프 안에 선언된 변수는 함수 밖에서 접근이 불가능합니다. 이유는 함수 스코프 안에서만 변수가 선언되기 때문입니다. 글로벌 스코프에 선언된 함수는 글로벌 변수 모두에 접근이 가능합니다. 함수 안에 선언된 자식 함수는 부모 함수가 접근 가능한 변수에 모두 접근이 가능합니다. 다른 함수에서 또 다른 함수 내부 변수에 접근하기 위해서는 글로벌 선언, 객체생성, 또는 파라미터로 전달하는 방법이 있습니다.

재귀함수(recursive function ) 
자기 자신을 호출하는 함수를 재귀함수라고 합니다. 아래 while() 구문을 재귀함수로 대체 가능합니다.

var x = 0;
while (x < 10) { // "x < 10" is the loop condition
   // do stuff
   x++;
}

function loop(x) {
  if (x >= 10) // "x >= 10" is the exit condition (equivalent to "!(x < 10)")
    return;
  // do stuff
  loop(x + 1); // the recursive call
}
loop(0);
클로저 
내부 함수는 외부 함수에 선언되어 있는 변수나 함수 값에 접근이 가능합니다.

var pet = function(name) {   // The outer function defines a variable called "name"
  var getName = function() {
    return name;             // The inner function has access to the "name" variable of the outer function
  }
  return getName;            // Return the inner function, thereby exposing it to outer scopes
}
myPet = pet('Vivie');
   
myPet(); 

var createPet = function(name) {
  var sex;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex === 'string' && (newSex.toLowerCase() === 'male' || newSex.toLowerCase() === 'female')) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet('Vivie');
pet.getName();                  // Vivie

pet.setName('Oliver');
pet.setSex('male');
pet.getSex();                   // male
pet.getName();                  // Oliver
arguments
객체 함수의 argument는 유사배열로 관리가 됩니다. 유사배열은 인덱스와 길이가 있지만, 배열의 모든 메소드를 사용할 수는 없습니다. 전달되는 arguments는 아래와 같은 형태를 가지고 있습니다. i값은 0부터 시작되며 전체 숫자는 arguments.length로 알 수 있습니다.

arguments[i]
함수 파라미터 
함수 파라미터는 두 가지 종류가 있습니다. 하나는 default 이며 나머지 하나는 rest 파라미터 입니다. 자바스크립트 함수에서 default는 undefined입니다. 하지만 기본값을 설정하면 NaN대신 원하는 결과값이 출력됩니다.

function multiply(a, b) {
  return a * b;
}

multiply(5);
NaN

function multiply(a, b = 1) {
  return a * b;
}

multiply(5);
5
rest 파라미터 문법은 arguments 의 값들을 배열로 반환합니다.

function multiply(multiplier, ...theArgs) {
  return theArgs.map(x => multiplier * x);
}

var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]
화살표 함수
화살표 함수는 코드를 획기적으로 줄어줍니다. 화살표 함수를 사용하면 function과 return 을 생략할 수 있습니다.

var a = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

var a2 = a.map(function(s) { return s.length; });

console.log(a2); // logs [8, 6, 7, 9]

var a3 = a.map(s => s.length);

console.log(a3); // logs [8, 6, 7, 9]
또한, this 연결을 예상한대로 할 수 있습니다.

// 기존
function Person() {
  var self = this; // Some choose `that` instead of `self`. 
                   // Choose one and be consistent.
  self.age = 0;

  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    self.age++;
  }, 1000);
}

// 개선
function Person() {
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

Comments

Popular posts from this blog

[dB's 리액트] Render Prop 사용하기

HOC는 코드 재사용 문제를 해결하기 위해 고안되었습니다. createClass 패러다임에서는 이러한 문제를 mixins으로 해결하였습니다. ES6 classes 가 등장하고 createClass는 사라지기 시작했습니다. 하지만 ES6 클래스는 mixins을 지원하지 않는다는 문제점이 있었습니다. 그 결과 HOC가 등장하였으며 재사용에 대한 이슈를 해결한 듯 보였지만, 기존 mixins이 가지고 있던 모든 이슈들을 해결한 건 아니였습니다. Render Props를 사용하면 mixins과 HOC가 가지고 있는 문제점들을 해결할 수 있습니다. Render Props 패턴은 함수로 이루어진 props를 이용하여  컴포넌트 간 코드를 공유하는 방법입니다. <DataProvider render={data => ( <h1>Hello {data.target}</h1> )}/> import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' // Instead of using a HOC, we can share code using a // regular component with a render prop! class Mouse extends React.Component { static propTypes = { render: PropTypes.func.isRequired } state = { x: 0, y: 0 } handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) } render() { return ( <div style={{ height: '100%' }} on...

[dB's 리액트] 리액트 16.3 무엇이 바뀌었나?!

리액트 16.3 버전이 새롭게 업데이트 되었습니다. 새로운 라이프 사이클과 API들이 소개 되었습니다: context API, ref forwarding API, ergonomic ref API 입니다. Context API Context API는 기존에도 제공되었습니다. 하지만, 상속 문제로 인해 사용 빈도가 적었으며 더 좋은 방법들로 대체되었습니다. 예로, redux, react-router, styled-components 등이 Context API를 기반으로 제작 되었습니다. Context는 CreateContext 함수를 이용해서 제작합니다. 이 함수는 Provider와 Consumer를 호출할 수 있습니다. Provider는 Context에서 사용할 값을 설정하고 Consumer는 설정한 값을 불러올 때 사용합니다. const ThemeContext = React.createContext('light'); class ThemeProvider extends React.Component { state = {theme: 'light'}; render() { return ( <ThemeContext.Provider value={this.state.theme}> {this.props.children} </ThemeContext.Provider> ); } } class ThemedButton extends React.Component { render() { return ( <ThemeContext.Consumer> {theme => <Button theme={theme} />} </ThemeContext.Consumer> ); } } 링크 https://hackernoon.com/how-to-use-the-new-react-co...

[dB's 몽고DB] MongoDB 데이터베이스 사용하기

오라클, MySQL 을 관계형 데이터베이스 라고 합니다. 이는 데이터를 담고 있는 복수 개의 테이블들이 긴밀하게 연결되어 있기 때문입니다. 이와 다르게, 몽고DB는 NoSQL 입니다. "SQL이 필요없다"가 아니라 "비관계형 데이터베이스 SQL" 이라는 뜻을 내포하고 있습니다. 이유는, DB에 접근하기 위해서는 결국 몽고DB에서 사용하는 쿼리문법이 필요하기 때문입니다. 특별히, 몽고DB는 자바스크립트 객체를 그대로 저장할 수 있어서 자바스크립트를 사용하는 노드에서 데이터를 저장하기에 적합합니다. 그렇기 때문에 데이터 저장, 조회 방식도 기존 SQL과 다릅니다. 이는 성능을 최우선으로 생각하기 때문에 고안된 방법이며 실시간 서비스나 대용량 트래픽을 감당할 수 있는 메시징 시스템등에 사용됩니다. 몽고DB는 데이터베이스의 테이블 대신, 여러 데이터가 모인 컬렉션(Collection)을 사용합니다. 즉, 데이터베이스는 컬렉션의 집합이고 각각의 컬렉션은 여러개의 문서객체(Document)를 가질 수 있습니다. 1. 몽고DB 설치하기 몽고DB 다운로드 센터로 이동 Installing with Homebrew 몽고DB 설치 brew install mongodb 데이터베이스 저장 폴더 만들기 mkdir -p /data/db 권한 부여하기 chown $USER /data/db 몽고DB 활성화가 되면서 27017 포트에서 연결을 기다린다는 메시지가 표시됨   mongod 몽고Shell 접속하기 새로운 터미널에서 mongo 2. 데이터베이스 생성과 입력, 삭제 데이터베이스 지정 use local 컬렉션 만들기 db.users.insert({name: '소녀시대'}) 컬렉션 문서조회 db.users.find().pretty() 문서삭제 d b.users.remove({name:/소녀시대/}) 로그인에 필요한 데이터 입력 db.users.insert({id: 'tes...