// 기명함수의 함수선언식
function a () { }
console.log(a.name) // a
// 아래 익명함수의 경우 name propery에 값이 할당되면 안되지만
// 브라우저들이 편의를 위해 자동으로 nmae 값 할당
// es6 부터 앞에있는 변수명을 name property에 할당하는 것으로 규칙 설정
const b = function () { }
console.log(b.name)
// 기명함수가 표현식형태로 변수에 할당됬을 때는
const c = function cc () { }
console.log(c.name) // cc
// 화살표 함수도 변수를 name property에 할당한다
const d = () => {}
console.log(d.name) // d
// 메소드도 마찬가지
const e = {
om1: function () {},
om2 () {},
om3: () => {}
}
console.log(e.om1.name, e.om2.name, e.om3.name) //om1 om2 om3
// 이전 프로토 타입 방식에서는 지원 안됨
function G(){};
G.method1 = function(){};
G.prototype.method2 = function(){}
const g = new G();
console.log(G.method1.name, g.method2.name) // "", ""
// 클래스는? 스테틱 메소드, 프로토타입 메소드 둘다 동일하게 지원
class F {
static method1 () {}
method2 () {}
}
const f = new F()
console.log(F.method1.name, f.method2.name)//method1, method2
// 함수 생성자 활용해보기
const f = function (a,b) {return a + b;}
// 마지막 인자로 블록문의 내용을 전달
const g = new Function('a', 'b', 'return a+b')
const g = new Function()
console.log(g.name)
// bind 의 경우 어떤 함수와 binding 되었는지 명시적으로 표시
function a () { }
const b = function () { }
const h = a.bind(b)
console.log(h.name) // bound a (b가 아니다)
// 잠깐 bind 활용 돌아보기
function a (x,y,z) {console.log(this, x, y, z);}
const b = a.bind({}, 1,2) // 첫번째 this, 두번째부터 인자들
b(3) // 3번째 z 인자만 넘겨주고 실행하면
// this, 1, 2, 3
//getter, setter 의 경우에도 nmae 프로퍼티가 명시적으로 나오게 됨
const person = {
_name: '재남',
get name () {
return this._name
},
set name (v) {
this._name = v
}
}
const descriptor = Object.getOwnPropertyDescriptor(person, 'name')
console.log(descriptor.get.name) // get name
console.log(descriptor.set.name) // set name
- 여기서
new
는 객체가 아니다.new.target
자체가 하나의 값이다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new.target
// 생성자 함수를 일반 함수처럼 사용하지 못하게 방어하는 코딩방법
function Person (name) {
if (this instanceof Person) { // new 키워드와 함께라면 this가 새로 생성될 instance를 가르킴
this.name = name
} else { // 일반함수라면 this 는 window를 가르키고, 결국 에러발생
throw new Error('new 연산자를 사용하세요.')
}
}
// 정상
var p1 = new Person('재남')
console.log(p1)
// 에러
var p2 = Person('성훈')
console.log(p2)
// 에러
var p3 = Person.call({}, '곰')
console.log(p3)
// p1 은 Person의 instance 이기 때문에 정상작동
// 여기가 바로 우회수단이다!!
var p4 = Person.call(p1, '곰')
console.log(p4) //곰
console.log(p1) //곰 this가 p1을 가르켰고 name에 곰이 할당됬다.
// 어떻게 해결할까?
// 위의 new 연산자 사용을 강제하기 위한 방법을 보다 명시적으로 하기 위해 new.target 등장
function Person (name) {
console.dir(new.target)
if (new.target !== undefined) {
this.name = name
} else {
throw new Error('new 연산자를 사용하세요.')
}
}
// 정상 작동
const p1 = new Person('재남') // new.target == Person || undefined
console.log(p1)
// 에러
const p2 = Person('성훈')
console.log(p2)
// 에러
const p3 = Person.call({}, '곰')
console.log(p3)
// 에러 드디어 우회를 막았다
const p4 = Person.call(p1, '곰')
console.log(p4)
// arrow function 은 this, new.target, agrument 를 bind 하지 않는다.
function Person (name) {
const af = n => {
this.name = n
console.log(new.target)
}
af(name)
}
const p1 = new Person('재남') // arrow function의 new.target도 역시 Person 이 나옴
const p2 = Person('성훈')
// 이전의 우회방법
function Person (name) {
this.name = name
}
function Android (name) {
Person.call(this, name)
}
// new.target === Android, 이기 때문에 오류 발생 x
const p1 = new Android('재남봇')
// 안전장치 걸기
function Person (name) {
console.log(new.target)
if (new.target === Person) { //undefined 보다 명시적으로 사용하기
this.name = name
} else {
throw new Error('Person 생성자함수를 new로 호출해야 해요!')
}
}
function Android (name) {
Person.call(this, name)
}
const p2 = new Android('재남봇')
// class의 상속에서 더 의미를 가지는 new.target
// new A 로는 활용할 수 없도록 제한 걸기
// javascript에서는 추상클래스(<-> 구체클래스)가 없기 때문에 이런 로직이 필요함
class A { // 추상 클래스처럼 흉내내기
constructor () {
if (new.target === A) throw new Error("A는 추상클래스 입니다.")
console.log(new.target)
}
}
class B extends A {
constructor () {
super()
}
}
const b = new B();
const a = new A();
stric mode
가 아닌 경우sloppy mode
에서는 브라우저마다 다른 동작이 발생한다. 예상이 불가능하다.strinc mode
의 경우에는 함수선언문도block scope
에 갇히게 된다.- es6 에서는 함수선언문을 쓰지말자
- 기본적으로 arrow function을 쓰자
- 객체 내부에서는: 메소드 축약형을 쓰자
- prototype과 관련해서는 class를 쓰자
- 그러면 나머지
generator
에서function*
형태로만 볼 수 있다. - 오롯이
function
만 있는 키워드가 등장할 일 자체가 없다.
// 함수 선언문은 let과 const 가 아니기 때문에 block에 갇히지 않고 hoisting 된다. 여전히 function scope인 것
if (true) {
a()
function a () { console.log(true) }
}
a()
// true
// true
// 그럼 이것도 되야하는데 이건 에러가 난다. 왜 그럴까?
// 이건 브라우저 별로 다르다. 크롬 -> 에러, firefox, safari -> 정상 작동,
a()
if (true) {
a()
function a () { console.log(true) }
}
if (true) {
a()
function a () { console.log(true) }
if (true) {
a()
function a () { console.log(false) }
}
}
a()
'use strict'
if (true) {
a()
function a () { console.log(true) }
if (true) {
a()
function a () { console.log(false) }
}
}
a()
// use stric 키워드를 쓰면 함수 선언이 block socpe에 갇히게 된다.
'use strict'
if (true) {
function a () { console.log(true) }
a()
}
a()