Javascript 기본(2)

JongIk Park·2021년 6월 11일
0

javascript

목록 보기
9/21
post-thumbnail

⛹️‍♂️ map() 구현

// definition
Array.prototype.myMap = function(callback) {
    arr = [];
    for (var i = 0; i < this.length; i++)
        arr.push(callback(this[i], i, this));
    return arr;
};

//tests
var arrs = ['dic tanin', 'boo radley', 'hans gruber'];
var numbers2 = [1, 4, 9];

var goodT = arrs.myMap(function(n) {
    return n;  // arrs배열을 mymap함수에 적용시킨다.
});

var squareRoot = numbers2.myMap(function(num) {
    return Math.sqrt(num);  // 제곱근을 구하는 함수 생성
});

console.log(goodT); // [ 'dic tanin', 'boo radley', 'hans gruber' ]
console.log(squareRoot); // [ 1, 2, 3 ]

⛹️‍♂️ 실행 컨텍스트를 이해하기 위한 자바스크립트 동작과정

  1. 변수, 함수 선언, arguments을 가진 활성 객체(Variable Object)생성
  2. Scope Chain 생성 및 초기화
    • 변수 초기화 : 변수 값에 undefined를 할당
  3. this 바인딩
  4. 코드 해석 및 실행
    • 변수 값 할당 : 변수에 실제 값을 할당

⛹️‍♂️ 변수 초기화 과정

  1. 변수 선언 : 변수를 활성 객체에 할당
  2. 변수 초기화 : 변수 값에 undefined를 할당
  3. 변수 실제 값 할당 : 변수에 실제 값을 할당

⛹️‍♂️ 실행 컨텍스트를 이해하기 위한 문제

  • 비동기 실행 방식인 setTimeout 을 이용한 예제
console.log("1");
function exec() {
  setTimeout(function() {
    console.log("2");
  }, 3000);
  setTimeout(function() {
    console.log("3");
  }, 0);
  console.log("4");
  setTimeout(function() {
    console.log(5);
  }, 1000);
}
console.log(exec());
// 위 코드 실행 결과 : 1, 4, 3, 5, 2
  • setTimeout의 지연시간이 0 일지라도 실행 컨텍스트가 다르기 때문에 1,4가 먼저 출력된다.

  • for문과 setTimeout

var i;
for (i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i); // 5, 5, 5, 5, 5
  }, 1000);
}
  • 위 코드를 실행시켰을 때, 0,1,2,3,4라고 추측하기 쉽지만, 실제로는 for문의 실행이 모두 끝난 후에 setTimeout의 콜백함수가 실행되기 때문에 숫자 5가 5번 출력된다.

⛹️‍♂️ arguments 객체

  • 함수 호출시에 넘겨진 실제 인자 값을 가진 배열
// 아래 함수 정의에 포함된 인자 값은 2개
function add(a, b) {
  console.dir(arguments);
}
console.log(add(1)); // Arguments(1), 0: 1
console.log(add(1, 2)); // Arguments(2), 0: 1, 1: 2
console.log(add(1, 2, 3)); // Arguments(3), 0: 1, 1: 2, 2: 3
  • arguments의 활용 : 메서드에 넘겨 받을 인자의 개수를 모를 때 유용
function sum() {
  for (var i = 0, result = 0; i < arguments.length; i++) {
    result += arguments[i];
  }
  return result;
}
console.log(sum(1,2,3)); // 6
console.log(sum(1,2,3,4,5,6)); // 21
  • 참고 : arguments는 length 속성과 'arguments[i]'와 같은 index를 지니지만 배열은 아니다.
    이러한 객체를 배열과 비슷한 객체(array-like-object)라고 한다.

⛹️‍♂️ apply() & call()

  • arguments에 apply(). call() 을 이용하여 실제 배열 메서드를 사용할 수 있다.
// apply() 적용 전
function sum() {
  console.log("arguments length : " + arguments.length);
  arguments.push(100); // Uncaught TypeError: arguments.push is not a function
  console.dir(arguments); // Arguments(3)
}
sum(1,2,3);
// 함수명.apply(대상, 인자 배열);
// apply() 적용 후
function sum() {
  var args1 = Array.apply(arguments);
  args1.push(100); // 0: 100
  console.dir(args1); // Array(1)

  var args2 = Array.prototype.slice.apply(arguments);
  args2.push(100); // 3: 100
  console.dir(args2); // Array(4)
}
sum(1,2,3);
  • apply(), call() 메서드는 결국 .apply()를 호출하는 함수를 실행하는 것이다. 그리고 호출하는 함수의 인자 값에 apply()로 넘긴 인자 배열을 넣어서 마지막 실행 결과만 대상에 연결한다.
function user(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
}
user.apply(window, ['kevin', 'durant']); // user.call(window, 'John', 'Doe'); 와 같음

console.log(window.firstName); // 'kevin'
console.log(window.lastName); // 'durant'

⛹️‍♂️ this 바인딩

  • 일반적으로 함수 내부에서 this를 사용하면 전역스코프(window)에 접근한다.
// 함수 선언식
var text = 'global';
function binding() {
  var text = 'local';
  console.log(this.text); // 'global'
  console.log(this); // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
}
binding();

// 함수 표현식
var text = 'global';
var binding = function() {
  var text = 'local';
  console.log(this.text); // 'global'
  console.log(this); // Window {stop: ƒ, open: ƒ, alert: ƒ, confirm: ƒ, prompt: ƒ, …}
}
binding();
  • 객체의 속성에서 함수를 선언하고 this를 사용하면 해당 객체를 접근한다.
var text = 'global';
var binding = {
  text: 'local',
  printText: function () {
    console.log(this.text); // 'local'
    console.log(this); // {text: "local", printText: ƒ}
  }
};
binding.printText();
  • 함수의 내부함수에서 this를 사용하면 전역 객체(window)에 접근한다.
var text = 'global';
var binding = {
  text: 'local',
  printText: function () {
    console.log(this.text); // local
    var innerFunc = function () {
      console.log(this.text); // global
    };
    innerFunc();
  }
};
binding.printText();

⛹️‍♂️ 스코프 체인을 이해하기 위한 예제

  • 전역 스코프와 함수 스코프의 구분
var a = 1;
var b = 2;
function func() {
  var a = 10;
  var b = 20;
  console.log(a); // 10
  console.log(b); // 20
}
func();
console.log(a); // 1
console.log(b); // 2
  • 아래는 내부함수 innerfunc에서 외부함수인 func의 변수에 접근하고 있다.
var a = 1;
function func() {
  var a = 2;
  function innerfunc() {
    return a;
  }
  console.log(innerfunc()); // 2
}
func();
  • 아래 예제는 func1의 실행 컨텍스트가 전역이라는 것에 주목한다.
var a = 1;
function func1() {
  return a;
}
function func2(func1) {
  var a = 2;
  console.log(func1()); // 1
}
func2(func1);

⛹️‍♂️ 클로져 정의 및 코드 예시

  • 외부함수의 실행이 종료되어 컨텍스트가 반환되더라도, 내부 함수로 종료된 외부 함수의 스코프에 접근이 가능한 기법 : 스코프 체이닝
  • 이미 생명주기가 끝난 외부 함수의 변수를 참조하는 함수
function func() {
  var a = 1;
  var cl = function () {
    console.log(a);
  };
  return cl
}
var result = func();
console.dir(result); // [[Scope]] 에서 Closure 함수임을 확인 가능
result();

  • 일정한 형식을 가진 템플릿에서 입력된 값에 따라 다른 결과물을 내는 코드
var str = [
  'hello ',
  '',
  ' world'
];

function completeSentence(name) {
  str[1] = name;
  return str.join('');
}
completeSentence('js'); //"hello js world"
  • 위 코드에 클로져를 적용했을 때
function completeSentence(name) {
  var str = [
    'hello ',
    '',
    ' world'
  ];
  return function () {
    str[1] = name;
    return str.join('');
  };
}
var result = completeSentence('js');
result();
  • 위 함수를 좀 더 기능 단위로 분할했을 때
function completeSentence(name) {
  var str = [
    'hello ',
    '',
    ' world'
  ];
  // 입력된 문자열로 문장을 완성하는 기능
  var complete = function () {
    str[1] = name;
    return str.join('');
  };
  // 문장 완성 기능을 클로져로 빼는 역할
  var closure = function () {
    return complete();
  };
  return closure;
}
var result = completeSentence('js');
result();  // "hello js world"

⛹️‍♂️ 클로져 활용

  • 클로저를 활용하여 java나 기타 언어처럼 속성 및 메서드의 범위를 정할 수 있다.
// 클로져로 Java 클래스와 유사하게 모듈화한 예제
var Module = (function() {
    var privateProperty = 'foo';
    function privateMethod(args) {
      console.log('private method');
    }

    return {
        publicProperty: '',
        publicMethod: function(args) {
          console.log("public method"); //undefined
        },
        privilegedMethod: function(args) {
          return privateMethod(args);
        }
    };
})();

Module.privilegedMethod(); // private method

💪

캡틴판교님의 블로그를 참고했습니다.

⛹️‍♂️ 추가공부

**1. join()

: 배열의 원소들을 연결하여 하나의 값으로 만든다.**

  • 문법 : var str1 = arr.join();
    배열에 있는 원소들을 하나의 값으로 만든다. 원소들의 구분은 콤마(,)로 하며, 원소들의 구분을 다른 문자로 하려면 ()안에 원하는 문자를 넣으면 된다.

  • 예제

<!doctype html>
<html lang="ko">
  <head>
    <meta charset="utf-8">
    <title>JavaScript</title>
  </head>
  <body>
    <script>
      var jbAry = [ 'Lorem', 'Ipsum', 'Dolor' ];
      var jbStr1 = jbAry.join();
      var jbStr2 = jbAry.join( ' / ' );
      document.write( '<p>' + jbStr1 + '</p>' );
      document.write( '<p>' + jbStr2 + '</p>' );
    </script>
  </body>
</html>

2. slice()

: begin 부터 end 전까지의 복사본을 새로운 배열 객체로 반환한다. 즉 원본 배열은 수정되지 않는다.

  • 문법 : slice(start[, end]);
    start(시작점) 에 대한 인덱스
    - undefined인 경우, 0부터 slice
    - 음수를 지정한 경우 : 배열의 끝에서부터의 길이를 나타낸다. slice(-2)를 하면 배열의 마지막 2개의 요소를 추출한다.
    - 배열의 길이와 같거나 큰 수를 지정한 경우 : 빈 배열을 반환한다.
    end(종료) 인덱스
    - 지정하지 않을 경우 : 배열의 끝까지 slice
    - 음수를 지정한 경우 : 배열의 끝에서부터의 길이를 나타낸다. slice(2,-1)를 하면 세번째부터 끝에서 두번째 요소까지 추출
    - 배열의 길이와 같거나 큰 수를 지정한 경우 : 배열의 끝까지 추출
    반환값 : 추출한 요소를 포함한 새로운 배열

3. splice()

: 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경한다. 이 메소드는 원본 배열 자체를 수정한다.
- 문법 : splice(start[, deleteCount[, item1[, item2[, ...]]]]);
start: 배열의 변경을 시작할 인덱스.

  • 음수를 지정한 경우: 배열의 끝에서부터 요소를 센다.
    배열의 길이보다 큰 수를 지정한 경우: 실제 시작 인덱스는 배열의 길이로 설정
  • 절대값이 배열의 길이보다 큰 경우: 0으로 세팅
    deleteCount: 배열에서 제거할 요소의 수.
    생략 / 값이 array.length - start보다 큰 경우: start부터의 모든 요소를 제거.
  • 0 이하의 수를 지정: 어떤 요소도 제거되지 않는다.
    item1, item2, ... : 배열에 추가할 요소.
  • 지정하지 않는 경우: splice()는 요소 제거만 수행한다.
  • 반환값: 제거한 요소를 담은 배열.
    아무 값도 제거하지 않았으면 빈 배열을 반환한다.
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var arr1 = arr.splice(10, 2, 'a', 'b', 'c');
console.log(arr); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, "a", "b", "c"]
console.log(arr1); // [11, 12]

splice() 함수를 사용하면 원본 배열인 arr이 변경된다.
10번째 인덱스부터 2개의 요소를 삭제하고 'a', 'b', 'c'를 추가했으므로
11과 12가 삭제되고 이 삭제된 요소들의 배열은 arr1 변수에 담긴다.

profile
신입 프론트엔드 개발자

0개의 댓글