[JavaScript] 함수 - 4

arguments 객체 this 객체

함수 호출시 함수 내부로 암묵적으로 전달되는 객체이다

arguments 객체

arguments 객체는 배열이 아니라 유사 배열 객체이다
length 프로퍼티가 존재함으로 배열과 유사하게 동작하지만 배열은 아니므로 배열 메서드를 사용할 수 없다

this 객체

함수 호출 패턴별로 this에는 다른 객체가 전달된다

객체 메서드 호출시 this 바인딩

자신을 호출한 객체에 this가 바인딩 된다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var myObject = {
name: 'foo',
sayName: function () {
console.log(this.name);
}
};

var otherObject = {
name: 'bar'
};

otherObject.sayName = myObject.sayName;

myObject.sayName(); //foo
otherObject.sayName(); //bar


함수를 호출할 때 this 바인딩

함수 호출 시 this는 전역객체에 바인딩 된다

1
2
3
4
5
6
7
8
9
var test = 'This is test';
console.log(window.test);

var sayFoo = function () {
console.log(this.test);
}

sayFoo();


내부 함수의 this 바인딩

내부 함수 호출 시 명시해주지 않는다면 전역객체에 바인딩 된다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var val = 100;

var myObject = {
val: 1,
func1: function() {
this.val += 1;
console.log('func1() called this.val : ' + this.val); // 2

func2 = function() {
this.val += 1;
console.log('func2() called this.val : ' + this.val); //101

func3 = function() {
this.val += 1;
console.log('func3() called this.val : ' + this.val); //102
}

func3();
}
func2();
}
};
myObject.func1();

관례상으로 this 객체의 바인딩을 저장하는 변수를 that이라 하며 다음과 같이 수정하면 객체 메서드 호출 시 바인딩 되는 this를 내부함수에서도 사용할 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var val = 100;

var myObject = {
val: 1,
func1: function() {
var that = this;
this.val += 1;
console.log('func1() called this.val : ' + this.val); // 2

func2 = function() {
that.val += 1;
console.log('func2() called this.val : ' + this.val); //3

func3 = function() {
that.val += 1;
console.log('func3() called this.val : ' + this.val); //4
}

func3();
}
func2();
}
};
myObject.func1();


생성자 함수 호출 시 this 바인딩

기존 함수에 new 연산자를 붙혀 호출하면 해당 함수는 생성자 함수로 동작한다

동작 원리

  1. 빈 객체를 생성하고 this를 바인딩한다
    • 이 때 this는 자신을 생성한 생성자 함수의 prototype 프로퍼티가 가리키는 객체이다
  2. this를 통한 프로퍼티 동적 바인딩
  3. 생성된 객체 리턴
    • 별도의 리턴문이 없을 경우 this로 바인딩된 새로 생성한 객체가 리턴된다
    • 만약 일반 함수를 호출할 때 리턴문이 없을 경우 undefinded가 리턴된다
1
2
3
4
5
var Person = function (name) {
this.name = name;
}

var foo = new Person('foo');


call과 apply 메서드를 이용한 명시적 this 바인딩

apply와 call 메서드는 Function.prototype 객체의 메서드 이므로 모든 함수에서 호출이 가능하다
다음과 같이 할당하면 Person 생성자를 호출하면서 명시적으로 this를 foo 객체에 바인딩 시킨다

1
2
3
4
5
6
7
8
9
10
11
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}

var foo = {};

Person.apply(foo, ['foo', 30, 'man']);

Person.call(foo, 'foo', 30, 'man');

또한 call이나 apply 메소드를 사용하면 유사 객체 배열을 배열로 변환해 사용할 수 있다

1
var args = Array.prototype.slice.apply(arguments);

객체 리터럴 방식 VS 생성자 함수를 통한 객체 생성 방식

객체 리터럴 방식으로 생성된 객체는 같은 형태의 객체를 재생성할 수 없다
또한 객체 리터럴 방식으로 생성된 객체의 프로토타입 객체는 Object이다
객체 리터럴 방식에서 객체 생성자 함수는 Object()이기 때문이다
생성자 함수를 통한 객체 생성 방식으로 생성된 객체의 프로토타입 객체는 생성자 함수 객체 이다
생성자 함수를 new를 붙히지 않고 호출할 경우 전역 객체에 바인딩이 된다

Author: Song Hayoung
Link: https://songhayoung.github.io/2020/07/12/Languages/JS/function4/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.