Javascript

javascript 문법 - 함수

간카레 2024. 1. 15. 00:19
반응형
SMALL

함수

// 함수(Function)

// 함수 선언문(Declaration)
// function hello() {}

// 함수 표현식(Expression)
// const hello = function () {}

// 호이스팅(Hoisting), 유효범위 안에서 함수 선언부가 가장 위에 있도록 javascript가 동작되는 것, 함수 선언에서만 발생하고 함수 표현에서는 발생하지 않는다.
hello();
// function hello() {
//   console.log('Hello!');
// }
const hello = function () {
  console.log('Hello!');
}

main.js:10 Uncaught ReferenceError: Cannot access 'hello' before initialization
    at Object.adjPd (main.js:10:1)
    at newRequire (index.63aff760.js:71:24)
    at index.63aff760.js:122:5
    at index.63aff760.js:145:3

할당 연산자를 통해서 함수를 할당하게되면 기명함수라도 호이스팅되지 않아서 에러가 발생한다.

const world = function hello() {
  console.log('Hello!');
}
world();


// 반환 및 종료

function hello() {
   // 기본 값 undefined, return 이후 코드는 동작하지 않음, 
  //  return 키워드가 없어도 undefined
}

console.log(hello()); // hello만 넣으면 함수 통째, hello() 넣으면 함수의 return값이 나온다


function plus(num) {
  if (typeof num !== 'number') {
    console.log('숫자를 입력해주세요!');
    return 0;
  }
  return num + 1;
}

return을 적절히 사용해서 함수를 잘 종료하자

// 매개변수 패던(Parameter pattern)
//// 기본값(Default value)

function sum(a, b = 1) {
  return a + b;
}

console.log(sum(1, 2));
console.log(sum(7));
매개변수에 기본값을 할당해서 매개변수에 값이 안들어왔을 때, 기본값을 넣어주게 할 수 있다.


//// 구조 분해 할당(Destructuring assignment)
// 객체 구조 분해 할당

const user = {
  name: 'HEROPY',
  age: 85,
  email: 'theseco@gmail.com',
}

function getName({ name }) {
  return name;
}
function getEmail({ email = '이메일이 없습니다.' }) {
  return email;
}

console.log(getName(user));
console.log(getEmail(user));

// 배열 구조 분해 할당

const fruits = ['Apple', 'Banana', 'Cherry'];
const numbers = [1, 2, 3, 4, 5, 6, 7];

function getSecondItem([, b]) {
  return b;
}

console.log(getSecondItem(fruits));
console.log(getSecondItem(numbers));


//// 나머지 매개변수(Rest parameter)

function sum(...rest) {
  console.log(rest);
  console.log(arguments); // arguments는 array-like 유사배열, 언제든지 함수 내에서 사용할 수 있다. 유사배열이라서 argumets는 reduce 메소드를 쓸 수 없다.
  
  return rest.reduce(function (acc, cur) {
    return acc + cur;
  }, 0);
}

console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4)); // 10
console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); // 55


// 화살표 함수(Arrow function)

// function sum() {};
// const sum = function () {};
// const sum = () => {};

// function sum(a, b) {
//   return a + b;
// }
const sum = (a, b) => a + b;

console.log(sum(1, 2)); // 3
console.log(sum(10, 20)); // 30


const a = () => {};
// 화살표 함수의 기본 구조, 항상 어떤 변수에다가 할당해서 만들어야 한다.
const b = x => {};
// 매개변수가 1개일 때는 소괄호를 생략할 수 있다.
const c = (x, y) => {};
// 매개변수가 2개 이상일 때는 소괄호를 생략할 수 없다.
const d = x => { return x * x };
const e = x => x * x;
// return 키워드가 맨 앞에 오는 경우에는 중괄호와 return 키워드를 생략할 수 있디ㅏ.
const f = x => {
  console.log(x * x);
  return x * x;
}
// 특정한 로직이 나오게 되면 중괄호를 생략할 수 없다.
const g = () => { return { a: 1 }};
// 반환하는 데이터가 객체 데이터라면 중괄호와 return 키워드를 넣어서 사용해야한다.
const h = () => ({ a: 1 });
// 아니면 소괄호로 객체를 묶어주면 생략할 수 있다.
const i = () => { return [1, 2, 3]};
const j = () => [1, 2, 3];
// 배열데이터는 괄호 모양이 다르기 때문에 중괄호를 생략할 수 있다.

화살표 함수를 사용하게되면 this 키워드가 다르게 해석된다.
이후에 내용이 있을 예정


// 즉시실행함수(IIFE, Immediately-Invoked Function Expression)

const a = 7;

const double = () => {
  console.log(a * 2);
}

double();

(() => {
  console.log(a * 2);
})();

// 화살표 함수 경우
(() => {console.log(a * 2);})();       // (F)(), 화살표 함수는 이렇게만 사용할 수 있다.

// 일반함수 경우
(function () {console.log(a * 2);})(); // (F)()
(function () {console.log(a * 2);}()); // (F())
!function () {console.log(a * 2);}();  // !F()
+function () {console.log(a * 2);}();  // +F()


((a, b) => {
  console.log(a);
  console.log(b);
})(1, 2);

((a, b) => {
  console.log(a.innerWidth);
  console.log(b.body);
})(window, document);


// 콜백(Callback)

const a = callback => {
  callback();
  console.log('A');
}
const b = () => {
  console.log('B');
}

a(b);


const sum = (a, b, c) => {
  setTimeout(c(a + b), 1000);
};
sum(1, 2, value => {
  console.log(value);
});
sum(3, 7, value => {
  console.log(value);
});


// https://www.gstatic.com/webp/gallery/4.jpg

// const loadImage = (url, cb) => {
//   const imgEl = document.createElement('img');
//   imgEl.src = url;
//   imgEl.addEventListener('load', () => {
//     setTimeout(() => {
//       cb(imgEl);
//     }, 1000);
//   });
// }


// const containerEl = document.querySelector('.container');
// loadImage('https://www.gstatic.com/webp/gallery/4.jpg', imgEl => {
//   containerEl.innerHTML = '';
//   containerEl.append(imgEl);
// });



const containerEl = document.querySelector('.container');
const loadImage = (url, cb) => {
  const imgEl = document.createElement('img');
  imgEl.src = url;
  setTimeout(() => {
    cb(imgEl);
  }, 1000);
};


loadImage('https://www.gstatic.com/webp/gallery/4.jpg', (imgEl) => {
  containerEl.innerHTML = '';
  containerEl.append(imgEl);
});


// 재귀(Recursive)

let i = 0;
const a = () => {
  console.log('A');
  i += 1;
  if(i < 4){
    a();
  };
};

a();


const userA = { name: 'A', parent: null, };
const userB = { name: 'B', parent: userA, };
const userC = { name: 'C', parent: userB, };
const userD = { name: 'D', parent: userC, };

const getRootUser = user => {
  if (user.parent) {
    return getRootUser(user.parent);
  }
  return user;
};

console.log(getRootUser(userD));
console.log(getRootUser(userC));
console.log(getRootUser(userB));
console.log(getRootUser(userA));


// 호출 스케줄링(Scaheduling a function call)

const hello = () => {
  console.log('Hello~');
};
const timeout = setInterval(hello, 2000);
const h1El = document.querySelector('h1');
h1El.addEventListener('click', () => {
  console.log('Clear!');
  clearInterval(timeout);
});

setTimeout(함수, 시간ms);
clearTimeout(함수);
지정 시간 후 함수 실행

setInterval(함수, 시간ms);
clearInterval(함수);
지정 시간 마다 함수 실행



// this
//// 일반 함수의 this는 호출 위치에서 정의
//// 화살표 함수의 this는 자신이 선언된 함수(렉시컬) 범위에서 정의

const user = {
  firstName: 'Heropy',
  lastName: 'Park',
  age: 85,
  // getFullName: function () {
  //   return `${this.firstName} ${this.lastName}`;
  // },
  getFullName: () => {
    return `${this.firstName} ${this.lastName}`;
  }
};

console.log(user.getFullName());

undefined undefined


function user() {
  this.firstName = 'Neo';
  this.lastName = 'Anderson';
  return {
    firstName: 'Heropy',
    lastName: 'Park',
    age: 85,
    getFullName: () => {
      return `${this.firstName} ${this.lastName}`;
    },
  };
};
const u = user();
console.log(u.getFullName());

Neo Anderson


function user() {
  this.firstName = 'Neo';
  this.lastName = 'Anderson';
  return {
    firstName: 'Heropy',
    lastName: 'Park',
    age: 85,
    getFullName: function () {
      return `${this.firstName} ${this.lastName}`;
    },
  };
};
const u = user();
console.log(u.getFullName());

Heropy Park


화살표함수에서 this는 화살표 함수를 감싸고 있는 함수의 값을 참조하고,
일반함수에서 this는 해당 함수의 값을 참조한다.



일반함수로 만들면 call이라는 메소드를 이용해서 다른데서 getFullName()메소드를 사용할 수 있다.
function user() {
  this.firstName = 'Neo';
  this.lastName = 'Anderson';
  return {
    firstName: 'Heropy',
    lastName: 'Park',
    age: 85,
    getFullName() {
      return `${this.firstName} ${this.lastName}`;
    },
  };
};

const lewis = {
  firstName: 'Lewis',
  lastName: 'Yang',
};

const u = user();
console.log(u.getFullName());
console.log(u.getFullName.call(lewis));


setTimeout(함수) 메소드 처럼 매개함수를 선언할 때
매개함수는 setTimeout 안에 선언되기 때문에
여기서 this를 쓰면 setTimeout함수 안에 있는 title을 찾게 되어서
this.title이 정상적으로 출력되지 않는다.
그렇기 떄문에 함수 안에 함수를 쓸때는 화살표 함수로 선언해서
this가 잘 동작할 수 있도록 하자


const timer = {
  title: 'TIMER!',
  timeout() {
    console.log(this.title);
    setTimeout(function () {
      console.log(this.title);
    }, 1000);
  }
};

timer.timeout();

반응형
LIST