모던 자바스크립트 20 ~ 22

해적왕·2023년 11월 30일
post-thumbnail

20장 strict mode

20-1 strict mode란

es5부터 자바스크립트 언어의 문법을 좀 더 엄격히 적용하여 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제를 일으킬 수 있는 코드에 대해 명시적인 에러 발생 시키는 것

20-2 strict mode의 적용

함수 몸체의 선두에 추가

'use strict'

function foo(){
	x = 10; // ReferenceError: x is not definded
}

foo();

20-3 전역에 strict mode를 적용하는 것 피하자

스크립트 단위로 적용된 strict mode는 다른 스크립트에 영향 주지않고 해당 스크립트에 한정 적용됨

(function(){
	'use strict';
   	// do something
})

실행 함수의 선두에 strict mode 적용

20-4 함수 단위로 strict mode를 적용하는 것도 피하자

즉시 실행 함수로 감싼 스크립트 단위로 적용하는 것이 바람직

20-5 strict mode가 발생시키는 에러

- 암묵적 전역

선언하지 않은 변수를 참조하면 ReferenceError가 발생

(function(){
  'use strict';
  x = 1;
  console.log(x);// ReferenceError : x is not defined
}()); 

- 변수,함수,매개변수의 삭제

delete 연산자로 변수, 함수, 매개변수를 삭제하면 SyntaxError 발생

(function(){
  'use strict';
  var x = 1;
  delete x; // SyntaxError : Delete of an unquqlified identifier in strict mode
}()); 

이케 사용하면 됨

var obj = { x: 1, y: 2 };
delete obj.x; // obj 객체의 x 프로퍼티를 삭제

console.log(obj); // { y: 2 }

- 매개변수 이름의 중복

중복된 매개변수 이름을 사용하면 SyntaxError 발생

(function(){
  'use strict';
  //SynyaxError: Duplicate paremeter name not allowed in this context
  function foo(x,x){
  	return x + x;
  }
  console.log(foo(1,2));
}()); 

20-6 strict mode에서 적용에 의한 변화

- 일반 함수의 this

strict mode에서 함수를 일반 함수로서 호출하면 this에 undefinded가 바인딩 (생성자 함수가 아닌 일반 함수 내부에서는 this 사용할 필요 없기 때문)

(function () {
  'use strict';

  function foo() {
    console.log(this); // undefined
  }
  foo();

  function Foo() {
    console.log(this); // Foo
  }
  new Foo();
}());

- arguments 객체

(function (a) {
  'use strict';
  // 매개변수에 전달된 인수를 재할당하여 변경
  a = 2;

  // 변경된 인수가 arguments 객체에 반영x
  console.log(arguments); // { 0: 1, length: 1 }
}(1));

21장 빌트인 객체

21-1 자바스크립트 객체의 분류

  • 표준 빌트인 객체
    표준 빌트인 객체는 ECMAScript 사양에 정의된 객체를 말하며, 애플리케이션 전역의 공통 기능을 제공한다.
  • 호스트 객체
    ECMAScript에 정의되어 있지 않지만 자바스크립트 실행 환경에서 추가로 제공하는 객체
  • 사용자 정의 객체
    표준 빌트인 객체와 호스트 객체처럼 기본 제공되는 객체가 아닌 사용자가 직접 정의한 객체를 말함

21-2 표준 빌트인 객체

Object, String, Number, Boolean, Symbol, Date, Math, RegExp, Array, Map/Set, WeakMap, WeakSet, Function, Promise, Reflect, Proxy, JSON, Error등 40여개의 표준 빌트인 객체 제공
Math, Reflect, JSON을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체

// String 생성자 함수에 의한 String 객체 생성
const strObj = new String('Lee'); // String {"Lee"}
console.log(typeof strObj);       // object

// Number 생성자 함수에 의한 Number 객체 생성
const numObj = new Number(123); // Number {123}
console.log(typeof numObj);     // object

// Boolean 생성자 함수에 의한 Boolean 객체 생성
const boolObj= new Boolean(true); // Boolean {true}
console.log(typeof boolObj);      // object

// Function 생성자 함수에 의한 Function 객체(함수) 생성
const func = new Function('x', 'return x * x'); // ƒ anonymous(x )
console.log(typeof func);                       // function

// Array 생성자 함수에 의한 Array 객체(배열) 생성
const arr = new Array(1, 2, 3); // (3) [1, 2, 3]
console.log(typeof arr);        // object

// RegExp 생성자 함수에 의한 RegExp 객체(정규 표현식) 생성
const regExp = new RegExp(/ab+c/i); // /ab+c/i
console.log(typeof regExp);         // object

// Date 생성자 함수에 의한 Date 객체 생성
const date = new Date();  // Fri May 08 2020 10:43:25 GMT+0900 (대한민국 표준시)
console.log(typeof date); // object

21-3 원시값과 래퍼 객체

문자열, 숫자, 불리언 등의 원시값이 있는데도 String, Number, Boolean등의 표준 빌트인 생성자 함수가 존재하는 이유

const str = 'hello';

// 원시 타입인 문자열이 프로퍼티와 메서드를 갖고 있는 객체처럼 동작함
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO

위 예제와 같이 str은 원시값인 문자열을 담은 변수인데, str.length, str.toUpperCase()와 같이 프로퍼티와 메서드를 호출할 수 있음

이는 원시값에 객체처럼 마침표 표기법으로 접근하면 자바스크립트 엔진이 일시적으로 원시값을 연관된 객체로 변환해 주기 때문

래퍼 객체
문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체

21-4 전역 객체

코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체
어떤 객체에도 속하지 않은 최상위 객체
브라우저 환경에서는 window가 전역 객체

- 빌트인 전역 프로퍼티

빌트인 전역 프로퍼티는 전역 객체의 프로퍼티를 의미함
주로 애플리케이션 전역에서 사용하는 값을 제공

Infinity

무한대를 나타내는 숫자값 Infinity를 갖음

//양의 무한대
console.log(3/0); // Infinity
//음의 무한대
console.log(-3/0); // -Infinity
//Infinity는 숫자값
console.log(typeof Infinity); // number

NaN

숫자가 아님을 나타내는 숫자값

console.log(Number('xyz')); // NaN
console.log(1*'string'); // NaN
console.log(typeof NaN); // number

undefined

원시타입 undefined 값

var foo;
console.log(foo); // undefined
console.log(typeof undefined); // undefined

- 빌트인 전역 함수

eval

자바스크립트 코드를 나타내는 문자열을 인수로 전달받음
전달받은 문자열 코드가 표현식이라면 eval 함수는 문자열 코드를 런타임에 평가하여 값을 생성 , 전달받은 인수가 표현식이 아닌 문이라면 eval 함수는 문자열 코드를 런타임에 실행, 문자열 코드가 여러 개의 문으로 이루어져 있다면 모든 문 실행

eval('1+2;') // 3
eval('var x =5;') // undefinded

문자열 코드가 여러 개의 문으로 이루어져 있다면 모든 문을 실행한 다음, 마지막 결과값 반환

eval('1+2; 3+4'); // 7

eval 함수 사용 금지
보안에 취약, 처리 속도 느림

isFinite

전달받은 인수가 정상적인 정상적인 유한수인지 검사하여 유한수이면 true, 무한수이면 false, Nan이면 false

isFinite(0); // true
isFinite(2e64); // true
isFinite('10'); // true
isFinite(null); // true
isFinite(Infinity);  // false
isFinite(NaN); // false

parseFloat

전달받은 문자열 인수를 부동 소수점 숫자, 즉 실수로 해석하여 반환

parseFloat('3.14'); // 3.14
parseFloat('10.00'); // 10

// 공백으로 구분된 문자열은 첫 번째 문자열만 반환
parseFloat('34 45 66'); // 34

// 첫번째 문자열을 숫자로 반환할 수 없다면 NaN 반환
parseFloat('He was 40'); // NaN

parseInt

전달받은 문자열 인수를 정수로 해석하며 반환

parseInt('10'); // 10
parseInt('10.123'); // 10

// 전달받은 인수가 문자열이 아니면 문자열로 변환한 다음, 정수로 해석 반환
parseInt(10.123); // 19

// 진법을 나타내는 기수를 전달 할 수 있음 
// 10을 2진수로 해석하고 그결과를 10진수 정수로 반환 
parseInt('10',2); // 2

2진수 리터럴과 8진수 리터럴은 제대로 해석 못함

encodeURI / decodeURI

encodeURI는 완전한 URI(Uniform Resource Idenrifier) 문자열로 전달받아 이스케이프 처리를 위해 인코딩
URI의 하위 개념으로 URL, URN이 있음
decodeURI는 이스케이프 처리 이전으로 디코딩

인코딩
URI의 문자들을 이스케이프 처리하는 것
이스케이프 처리
네트워크를 통해 정보를 공유할 때 어떤 시스템에서도 읽을 수 있는 아스키 문자 셋으로 변환하는 것
예) 특수 문자인 공백 문자는 %20, 한글 '가'는 %EC%9E%90

한글,공백또는 <> 이스케이프 처리하여 야기될 수 있는 문제 예방해야 함

encodeURIComponent / decodeURIComponent

encodeURIComponent URI 구성 요소를 인수로 전달받아 인코딩
쿼리 스트링 구분자까지 인코딩
decodeURIComponent 매개변수로 전달된 URL 구성 요소 디코딩

- 암묵적 전역

var x = 10; // 전역 변수
function foo(){
 // 선언하지 않은 식별자에 값을 할당
  y = 20; // window.y = 20;
}

foo();

// 선언하지 않은 식별자 y를 전역에서 참조 가능 
console.log(x + y); // 30

22장 this

22-1 this 키워드

const circle = {
  radius: 5,
  getDiameter() {
    // this는 메서드를 호출한 객체를 가리킴 
    return 2 * this.radius;
  }
};

console.log(circle.getDiameter()); // 10
function Circle(radius) {
  // this 생성자 함수가 생성할 인스턴스 가리킴 
  this.radius = radius;
}

Circle.prototype.getDiameter = function () {
  // this는 생성자 함수가 생성할 인스턴스 가리킴 
  return 2 * this.radius;
};

const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
//this는 어디서든지 참조 가능
// 전역에서 this는 전역 객체 window
console.log(this); // window

function square(number) {
  // 일반 함수 내부에서 this는 전역 객체 window
  console.log(this); // window
  return number * number;
}
square(2);

const person = {
  name: 'Lee',
  getName() {
    // 메서드 내부에서 this는 메서드를 호출한 객체
    console.log(this); // {name: "Lee", getName: ƒ}
    return this.name;
  }
};
console.log(person.getName()); // Lee

function Person(name) {
  this.name = name;
  // 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
  console.log(this); // Person {name: "Lee"}
}

const me = new Person('Lee');

22-2 함수 호출 방식과 this 바인딩

- 일반 함수

this에는 기본적으로 전역 객체가 바인딩

function foo() {
  console.log("foo's this: ", this);  // window
  function bar() {
    console.log("bar's this: ", this); // window
  }
  bar();
}
foo();

엄격 모드일 경우 undefined가 바인딩

function foo() {
  'use strict';

  console.log("foo's this: ", this);  // undefined
  function bar() {
    console.log("bar's this: ", this); // undefined
  }
  bar();
}
foo();

- 메서드 호출

메서드 내부의 this는 메서드를 호출한 객체에 바인딩

const person = {
  name: 'Lee',
  getName() {
    // 메서드 내부의 this는 메서드를 호출한 객체에 바인딩
    return this.name;
  }
};

// 메서드 getName을 호출한 객체는 person
console.log(person.getName()); // Lee

- 생성자 함수 호출

생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스 바인딩

// 생성자 함수
function Circle(radius) {
  // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킴
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

- Function.prototype.apply / call / bind 메서드에 의한 간접 호출

apply, call, bind는 Function.prototype의 메서드
첫 번째 인수로 전달한 객체에 바인딩

0개의 댓글