"매개변수"와 "인자"의 차이.
// a라는 함수, arg1 이라고 하는 매개변수가 있다고 한다면
function a ( arg1 ) {
}
# 1은 인자 : argument
a(1)
즉, arg1 : parameter > 매개변수
1 : argument > 인자 ( 들어가는 값 )
function sum( ) {
let i = 0
for( let i = 0; i < arguments.length; i ++ ){
console.log(arguments[i])
}
}
sum(1,2,3,4)
Javascript는 매우 관대한 언어이다.
sum 이라는 함수를 보면, 지금은 매개변수가 없다.
그런데 인자 1, 2, 3, 4 총 4개를 전달했다.
JS는 함수의 매개변수를 정의하지 않은 경우에도,
인자의 수를 마음대로 지정할 수 있다.
매개변수가 3개 인데, 인자가 1개 등, 수가 달라도 괜찮다.
그렇다면, sum 함수 내에 있는 'argument' 라는 것은 무엇일까 ?
sum 함수내에서 따로 변수로 선언한적도 없는데,
for문안에서 저렇게 사용해도 되는 이유는 무엇일까 ?
arguments 라고 하는 것은
약속되어있는, 특수한 이름의 변수명이고,
그 안에는, arguments라고 하는 '유사배열, 객체'이 담겨있다.
이 배열 안에는
사용자가 전달한 '인자'가 arguments 라고 하는 유사배열, 객체에 들어가있고
arguments를 통해, 사용자가 전달한 인자에 접근할 수 있는 것이고,
arguments 객체는, 배열과 유사한 사용법을 지니므로
arguments.length 와 같이, 배열 method를 사용할 수 있는 것이다.
'this의 값은, 함수를 호출하는 방법에 의해 결정된다'
'또한, 호출하는 방법과 무관하게 this를 묶어버리는 bind 라는 함수도 존재한다'
someone.whoAmI() // 자신을 호출한 somone이라는 객체가 나온다
var myWhoAmI = someone.whoAmI;
/*
분명히 위의 코드를 통해서
someone.whoAmI() 가 myWhoAmI 에 할당되었으니
같은 값이 출력될 것이라고 생각했으나
ex. result : window ~~
가 호출된 것을 확인할 수 있다...?
왜 ? 호출하는 방법이 달라졌기 때문이다.
this....는 누가 호출했냐 ! 이다
somone.whoAmI() 의 경우,
whoAmI()를 호출한 애는,
someone !
'.' 이 중요하다 !
someone. 인 것이다 !
반면, myWhoAmI() 의 경우 ,
글로벌에 존재하고
글로벌은 window 에 의해 호출되기 때문에
사실상 window가 호출하는 셈이다.
브라우저가 그냥 실행한 것이다.
*/
myWhoAmI()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button class="btn">btn</button>
<script>
var someone = {
name : 'codejong',
whoAmI : function(){
console.log(this)
}
}
someone.whoAmI() // 자신을 호출한 somone이라는 객체가 나온다
var myWhoAmI = someone.whoAmI;
/*
분명히 위의 코드를 통해서
someone.whoAmI() 가 myWhoAmI 에 할당되었으니
같은 값이 출력될 것이라고 생각했으나
ex. result : window ~~
가 호출된 것을 확인할 수 있다...?
왜 ? 호출하는 방법이 달라졌기 때문이다.
this....는 누가 호출했냐 ! 이다
somone.whoAmI() 의 경우,
whoAmI()를 호출한 애는,
someone !
'.' 이 중요하다 !
someone. 인 것이다 !
반면, myWhoAmI() 의 경우 ,
글로벌에 존재하고
글로벌은 window 에 의해 호출되기 때문에
사실상 window가 호출하는 셈이다.
브라우저가 그냥 실행한 것이다.
*/
myWhoAmI()
// html 상의 버튼을 클릭할 때
var btn = document.getElementById('btn')
/*
예상한 결과는
{
name : 'codejong',
whoAmI : f
}
실제 결과는
<button class="btn">btn</button>
즉, html element가 나오는 것이다.
자. 자세히 보면,
여기서는 somone이 whoAmI 를 호출한 것이 아니다.
그저 somone.whoAmI()라는 함수를 넘긴 것 뿐이다.
그리고 그 함수를 꺼내서 버튼한테 준것이고
버튼을 누르면, 그 함수를 실행하라고 한 것.
즉, 호출한 것은, "버튼"인 것이다.
btn.addEventListener('click', someone.whoAmI)
결국
"호출한 놈 == THIS" !
*/
btn.addEventListener('click', someone.whoAmI)
// 'someone'을 this라고 하겠다는 것이다.
// 즉, bindedWhoAmI는 someone을 무조건 this로 받겠다 !
let bindedWhoAmI = myWhoAmI.bind(someone)
/*
< 실행결과 >
{
name : 'codejong',
whoAmI : f
}
*/
console.log(bindedWhoAmI())
</script>
</body>
</html>
let bob = function(num, str){
console.log('bob', num, str, this)
return true
}
let bill = {
name : 'Bill Murray',
movie : 'Lost in Translation',
myMethod : function(fn){
// fn : passed in arg
}
}
if code is constructed like above ,
> bill.myMethod(bob)
we will see
'''
bob undefined undefined
Window ~~ // since 'this' refers to 'Window' which calls bob !!
// it's not 'bill' that calls bob !
// if you see the 'myMethod' function,
// fn() >> it's not bill.fn()
// fn() >> it's just called by 'window' object
'''
when we use
'call' , 'apply' , 'bind' method ,
we have to consider the 'context' in which
the function is running,
'''
_bob.call(bill , 2, 'goodbye' )
'''
I want bob function to run !
'bill' object is a context for 'bob' function to run
we can list out any kinds of args, we want to pass in
'''
bob 2 goodbye
{ name : Bill Murray , movie : 'Lost in Transitor', myMethod : f }
'''
as you can see,
'this' is now pointing the 'bill' object, not that 'Window'
which means that,
'context' becomes 'this'
'''
bob.apply(bill, [ 2, 'good bye'] )
'''
we will see the same result !
what if we want to run below code ?
'''
bill.myMethod(bob, 4, 'ciao' ) ??
'''
we need to revise the code as below
'''
let bob = function(num, str){
console.log('bob', num, str, this)
return true
}
let bill = {
name : 'Bill Murray',
movie : 'Lost in Translation',
myMethod : function(fn){
// fn : passed in arg
fn.apply(bill, [ arguments[1], arguments[2] ] )
// same : fn.apply( bill , n, s )
}
}
'''
so we are saying that,
'fn' that runs in 'bill' context,
will take 2args which are
'arguments[1]' , 'arguments[2]'
it does pretty much the same thing as 'call' or 'apply' function.
unique characteristic of bind is that,
you can save it in a variable to use it later on.
'''
bob.bind(bill, 5, 'hasta la vista' )
'''
above code itself, does nothing
why ?
in contrast to 'call' or 'apply' method,
'bind', prepares the function to be called later on ,
instead of running it right away,
it passes back the copied array
'''
let fred = bob.bind(bill, 5, 'hasta la vista' )
fred()
'''