명시적인(뜻이 분명한,확실하게) 함수 콘텍스트를 지정할수 있는 메소드

Function.prototype.apply

apply(thisArg,[argsArray]);

Function.prototype.call

call(thisArg,[, arg1[,arg2[,....]]])

Function.prototype.bind

bind(thisArg,[,arg1[,arg2[,...]]]);


1. apply

두개의 매개 변수를 가진다.

(  (1)  Function(),    (2) [......])

(1) 해당과 같이 펑션을 가지게 된다. 함수 콘텍스트로 사용할 펑션 객체 

(2) [ ] 형태의 Array 를 인자로 받는다.


2. call 

두개의 매개변수를 가진다. (apply 와 마찬가지로)

(  (1)  Function(),    (2) ......)

(1) 해당과 같이 펑션을 가지게 된다. 함수 콘텍스트로 사용할 펑션 객체 (apply 와 같음)

(2) 배열의 형태가 아닌 인자를 그대로 직접 받는다. 



function foo(){};


apply (foo,[1,1,1,1]);

call ( foo,1,1,1,1);


실제 사용 테스트 코드 

function moveFunction(){
    var result = 0;
		for(var i=0;i<arguments.length;i++){
				result+=arguments[i];}

	this.result = result;
}
var test1 = {};
var test2 = {};

moveFunction.apply(test1,[3,3,3,3]);

moveFunction.call(test2,1,1,1,1);

console.log("test1 result value : " ,test1.result);
console.log("test2 result value : " ,test2.result);



결과

test1 result value :  12

test2 result value :  4



두 메서드는 인자의 차이만 있을뿐 거의 같은 방식으로 동작하게 된다.


apply 냐 call 이냐의 선택은 인자를 어떻게 사용하여야 하는지에 따라 다를것 같다.


배열 형식으로 사용할거면 apply 인자를  한두개씩 직접 전달해야되는 경우 call 


을 선택하여서 사용하면 될것 같다.


결과를 보면 알겠지만 함수의 기능을 가져다 쓰면서 result값을


this.result를 통해서 작성하게 되어있다.


test1과 test2의 각각 컨텍스트를 가질수있게 해주는 메서드로 보면된다.


3. bind

sddfsf



Posted by 깍돌이

앞서 JavaScript의 Scope Chain 에 대해 확인 하였습니다.

(기본적으로 var 에 대해서는 function scope를 가지며 ES스펙 -> 이부분은 따로 포스팅)

이지만 let과 const를 사용할시에는 block scope를 가질수 있습니다.(블록 { } 안에서만 유효한)


또한 function 의 경우에는 참조 범위까지 호이스팅 

그렇지 않을 경우에는 undefined로 되는점 까지확인 하였으며



function foo()

{

variables_; // undefined

function_; // "HI"

   

var variables_;

function function_ (){console.log("HI");

오늘은 함수의 args(인자) param(파라미터) 에 대해서 확인 해보도록 하겠습니다.


간단하게 함수내 에서 this까지도 확인하려고합니다.


1. args 


function foo()
{
  console.log(this);
  console.log(arguments);
}
foo("arg1","arg2","arg3");


해당 코드를 브라우저에서 돌렸다면 

this - > Window (브라우저의 WIndow 객체가 나타납니다.);

arguments -> 인자로 들어온 인자들을 전부 표시합니다.


결과 : (Chrome 브라우저 기준으로 하였으며 세부값은 다를수 있습니다.);


[Chrome 브라우저에서 해당 코드 호출시 console에 찍히는 값 ]


[Node .js를 통해서 vscode 에서 돌린 코드 결과 값]


해당 사진이 작아서 안 보일수 있지만 


문자열로 옮겨 놓으면


노드 v9.6.1이(가) 감지되었으므로 검사 프로토콜로 디버그합니다.

node --inspect-brk=28848 app.js 

Debugger listening on ws://127.0.0.1:28848/89ba9122-cdb0-4320-b30a-a449b925fed2


null: global {console: <accessor>, DTRACE_NET_SERVER_CONNECTION: , DTRACE_NET_STREAM_END: , DTRACE_HTTP_SERVER_REQUEST: , DTRACE_HTTP_SERVER_RESPONSE: , …}

null: Arguments(3) ["arg1", "arg2", "arg3"]


와 같이 나온다


브라우저와의 차이점에서는


arg값은 똑같이 나타나지만 실제로 가리기키는 this에 대해서는 다르게 표시 됨을 확인할수 있다. ( 해당 this에 대해서는 추후 다시 Subject를 가지고 할예정)


여기까지 arguments 에 대한 인자 객체를 알아 보았습니다.


실제로 인자를 넘겼지만 function 에서 받는 파라미터가 없어도 arguments 를 통해서 지정하지 않은 인자가 들어왔는지 확인 하실수 있습니다.


2 Parameter


arguments 인자와 비슷하지만 차이점이 있습니다. 


함수부터 작성해보겠습니다.

위의 작성된 foo 함수와 같지만 다른점이 있습니다.

function foo(param1,param2)
{
    console.log("paramTest > param 1 ?",param1," : param2 ? " ,param2);
    console.log(this);    
    console.log(arguments);
}
foo("arg1","arg2","arg3");
    


위의 함수와 다르게 param1과 param2가 function 옆에 파라미터로 선언이 되어있습니다.

이경우에는 어떤식으로 쓸수 있을지 확인해보면


해당 함수의 결과를 보겠습니다.


[Chrome 브라우저에서 확인시]




인자값은 똑같이 들어오지만 param 으로 지정시에는 순서대로 param 로 들어오는 점이 확인됩니다.


이처럼 parameter를 지정하여서는 가독성 높은 변수 활용을 기대할수 있습니다.


함수 파라미터 지정을 param2까지 들어왔지만 뒤에 예상치 못한 인자들을arguments 객체를 통해서 할수 있는 점이 있습니다. 



Posted by 깍돌이

JavaScript의 Scope는 Block(블록 { } ) 이 아닌 Function(함수)에 의해 정해집니다.


블록 안에서 선언된 변수 들은 블록 안에서 끝나지 않고 Function(함수) 단위로 가게 됩니다.


그에 해당 하는 테스트 샘플 코드입니다.

function foo()
{
		console.warn('__Before__');	
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');
		/*
			first not exist  'number'로 비교하였지만 undefined로 호이스팅(끌어올리다) 
			Internal exist   'function' 으로 비교하여 참조 의 호이스팅이 되는점 확인 -> 실제 함수 사용까지 가능)

		*/
		var first = 1;
		function Internal(){console.log("Internal exist");}

		console.warn('__after__');
		typeof first ==='number' ? console.log('first exist') : console.error('first not exist');
		typeof Internal==='function' ? Internal() : console.error('not exist');

		/*
			first exist 
			Internal exist 
		*/
		if(first===1){var third = 3;};

		typeof third==='number' ? console.log('third exist') : console.error('third not exist');
		
		/*
			third exist  var third 선언은 if(first===1) 분기를 타고 블록(block) 안에 선언되었지만 밖에서도 참조가 가능
		*/

}
foo();






호이스팅(일명 끌어올리기) 에 대해서는 매우 중요하다기보다는 


이런느낌으로 알고 지나가는게 좋을 것 같습니다.


펑션은 호이스팅으로 참조까지 가능하지만


변수(var)는 undefined로 호이스팅이 되는점만 알면 되며 


let 과 const에 대해서는 호이스팅은 되지않는다고 는 하지만 실제로 디버거시에 undefined로


호이스팅되는점은 확인은 되는데


되든 안되든 변수의 경우 undefined로 올라오기 때문에 이에 대해서는 더 깊게 생각하지 않기로


했습니다.


Posted by 깍돌이

C언어는 절차 지향 언어라고 할수 있다. 해당 내용은 절차지향에 대한 이야기 일뿐


자바스크립트와는 많은 관련이 있진 않습니다. C를 하다 넘어 왔기 때문에


자바스크립트도 절차지향으로 보여 잘못생각하였던 부분에 대한 설명입니다.



#include 
using namespace std;


int main(void)
{
	printf("CPP Test\n");

	show(); //show 식별자를 찾을수 없습니다. 에러 
	return 0;
}

 void show() 
{
	printf("Show Call");
}

const int OpenResult(int flag) 
{


}



// 해당 호출이 불가능해지기 때문에


// 실제 사용시에는

// 이 처럼 코드 상단에 미리 선언을 하고 원형을 하단에 작성한다.C 의경우


#include 
using namespace std;

// 절차 선언 
void show();
int main(void)
{
	printf("CPP Test\n");

	show();
	return 0;
}

 void show() 
{
	printf("Show Call");
}




의 형태로 지원되어야 한다. 절차지향




자바스크립트 또한 그럴것이라 생각 하였지만 실제 JS에서 유효범위는 생각과는 달랐다.



function external(){

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

function Internal (){};

typeof Internal ==='function'  ?  console.log("Internal  exist") : console.log("Internal  not exist");

window.Internal === undefined ? console.log('Internal is not window exist' ) : console.log('Internal window exist');

window.external === undefined ? console.log('external is not window exist') : console.log('external window exist');
}

external();







결과


Internal  exist

Internal  exist

Internal is not window exist

external window exist




1번째에


typeof Internal ==='function 부분에서 exist로 넘어가는것으로 보아


절차적으로 코드가 생성되는것으로 보였지만 


자바스크립트의 유효범위는 블록이 아니라 함수에 의에 정의된다고 할수있다.


여기까지보면 뭔가 큰 차이가 안 느껴져서  자바스크립트의 Scope Chain 은 Function 이라는 예제를 하나 더 들수 있다.

C의 경우
 void show() 
{
	printf("Show Call");

	for (int i = 0; i < 5; i++)
	{
		int b = 10;

	}
	printf("B is %d", b);
}

// 와 작성시 이미 printf b 에서 컴파일 하기도전에 validation 에 걸립니다. b가 정의되어있지 않습니다. 
// C,C++에서는 Scope Chain 은 Block Scope를 가진다는 것을 알수 있습니다. 


JavaScript 의 경우
function show()
{
   for (var i=0;i<5;i++)
   {
			var b = 10;
   }
console.log("B is ",b);
}
show();


// 결과
// B is  10


자바 스크립트의 Scope Chain 은 위와 같이 Function 을 가지게됩니다.


이에 대해서 JS 작성시 실수하였던 점이

   for(var i=0;i<10;i++)
  {   
        for(var j=0;j<10;j++)
        {
              for(var i=0;i<5;j++)
              {
               }

         }

        
  }
       



해당 식의 코드를 한번 짤일이 있었는데 디버그 하다가 애를 먹었던적이 있습니다.


처음 i 0 ~을 돌다가 3번째 for문에서 i가 4인 채로 끝나기 때문에  자기 밖으로나가면 i2가 된상태로 돌아야하지만


i4인채로 끝나서


첫번째 포문에서 i 0 1,2,3 부분이 건너 뛰고 바로 4로 넘어가는 현상이 생겼습니다.


js에서는 function Scope Chain 을 가지기 때문에 해당 부분에 유의 하여야 합니다.


최근 ES스펙이 오름에 따라서 let변수가 해당 C,C++의 block scope 를 가지게 도와주지만 해당 내용은 뒤에 작성하도록 하겠습니다.





Posted by 깍돌이

일반적인 웹 브라우저에서의 이벤트 루프는 


단일 스레드에서 동작 을 하고 있으며 이사실을 꼭 인지하고 있어야 합니다.


전에 봤던 JavaScript는 1종 객체 (First-Class Object)라는 점과 같이 알아야 합니다.


function test() {};


는 언제든지


var fn = test; 가 가능 하다는 점


브라우저는 단일 스레드에서 이벤큐를 이용하여 들어오는 이벤트를 처리하게 되는데 


모든 이벤트를 큐에 들어온 순서대로 진행이 됩니다.


C언어 하실 때 자료구조에서 queue(큐)를 stack(스택)과 같은 공부 를 하실 때 


stack 에서는 push pop 이라는 용어를 썻지만


C에서는 front rear 라는 말도 있고 put get 뭐 이부분은 C에서 나오는 부분이니


중요한 점은 FIFO(First In First Out) 이라는 점입니다.


먼저 들어온 놈이 먼저 나간다는 말이 될수 있겠죠


대학로 아서 연극 표를 사러 갈때는 생각 하면 줄을 서서 먼저 표를 받게되면 바로 나가게 되는


모습을 생각 하면 될것 같습니다.


매표소는 1개 있죠 대부분 


브라우저도 메시지 큐 1개(매표소) 에서 티켓터(이벤트) 들을 기다리면서


행동을 하나씩 하나씩 처리해주는 방식을 가집니다.



** 브라우저 자체의 JavaScript 인터 프린터의 경우 단일 스레드 를 가지고 있습니다. 


-> JavaScript는 멀티 스레딩을 지원하지 않음 


-> Web Worker 사용을 하시는 분들은 논외 





** 해당 관련한 스터디 및 관련 책들에 대한 자료인데 아직까지는 이해가 되지 않는 부분이 있습니다.


브라우저는 브라우저별로 각각 다른 엔진을 쓰고 있고 


Chrome 28 이전 - > webkit

Chrome 28 이후 -> Blink

IE -> Trident

Gecko ->  FireFox 


각 브라우저별 엔진이 다릅니다. 엔진이 다르기 때문에 렌더링 되는 동작이 다릅니다. 

(화면 및 다른 쪽 렌더링으로 자바스크립트의 이벤트 방식은 위와 같습니다.)











Posted by 깍돌이

자바스크립트 작성에 의해서 함수를 이해하는 것은 매우 중요합니다.


우선적으로 알고 들어가야 할 부분 은 


자바스크립트 함수는 1종 객체 (first-class Object) 라는 점을 알고 가야 합니다.


이를 뜻하는 점은


기존에 C에서의 가정하면


void show () const 

{

printf("Function Show");

}


int fn_value = 1;


에 경우가 있을때 fn_value는 int 형 변수이며


show는 함수이기 때문에


fn_value = show ; 라는 동작이 성립이 되지 않습니다.


위의 상황을 자바스크립트로 변경을 해보게 되면


function show ()  

{

console.log("Functioin Show");

}


var fn_value = 1;


fn_value = show; 가 가능해지기 때문에


자바스크립트에서의 함수는 1종 객체 (First-Class Object)라는 점을 알고 가야 합니다. 


위에 설명에서 C의 경우는 성립이 되지않아 저 코드 상태로 확인이 할수있는 점이 없습니다. 


show를 부르고싶다면


int fn_value는 그대로 놓은 상태에서


show(); 를 호출하여야 하지만


자바스크립트 코드에서는


fn_value = show; 한 후에


fn_value(); 로 하게되면


Function Show를 확인 하실수 있습니다.

function show()
{
		console.log("Function Show");
}
 	
	
var fn_value =1;
	fn_value = show;
	fn_value();


해당 사항에 대해서 이해를 하고 넘어 가야 합니다.


이해가 되었다면


1종 객체란 무엇인가



리터럴 로 생성 될수 있다.



변수,배열 요소, 다른 오브젝트의 프로퍼티에 할당이 가능


함수의 인자로 전달 가능


함수의 결과 값으로 반환 가능


동적으로 생성된 프로퍼티를 가질수 있다.


동적으로 생성된 프로퍼티라 함은

		var obj_ = [];
		obj_.push({name:"test",age:"18"});
		console.log(obj_[0]);

		obj_.push({name:"testB",age:"20",addProperty:"addProp"});
		console.log(obj_[1]);



와 같이 생성되는 점을 말할수 있다. Chrome 브라우저 개발자 도구(F12)을 누른후 콘솔 탭에서 해당 코드를 실행해보면



추가 하는형식에 따른 프로퍼티들이 동적으로 생성됨이 확인된다.



여기까지 대충 이해가 된 상태라면



브라우저에서 window 객체에 대한 특정 함수를 할당 하는 경우

 function browserInit(){
                   // do thing
} 
  window.onload = browserInit;

  // 방식을 사용 하는 것 보다 


  window.onload = function () {  

           // do thing 

  }
//  혹은
  window.onload  = () => {

// do thing 

}
 // 의 방식을 사용할수 있으며 위의 방식보다 코드도 짧아지고 좋다고 생각된다.








Posted by 깍돌이

비동기 테스트 



메인 (A) 가  실행 될때


테스트 스위트 (A-a)

테스트 케이스(A-a-001)

테스트 케이스(A-a-002)

테스트 케이스(A-a-003)

테스트 케이스(A-a-004)



테스트 스위트 (A-b) ...

....



와 같이 진행 되는 경우에 아래 보이는 케이스들이 동기 방식 일때


** 테스트 를 하기 위한 로직은 비동기,동기 둘다 작성할수 있는 경우가 있지만 해당 내용은 배제 하도록 하겠습니다.  케이스 001을 파일 쓰기 작업을 기준으로 설명 드리지만 해당 작업은

비동기로 짤수 도 있지만 동기로 짤수도 있습니다.


동기 : 케이스(001) 가 실행이 끝난후에 결과를 return 하고 002 로 넘어가는 방식

ex :  케이스 001 이  log 10만 줄을 쓰는 작업을 동기식으로 확인 한다고 가정하게되면


언젠가는 10만 줄을 작업 후에 return 을 하게 됩니다.


->결과에 대한 기대가 가능합니다.  


해당 의 경우에 대해서는 결과에 대한 기대 가 가능하기 때문에 expect 를 작성하여서 테스트 코드를 작성하기가 수월합니다.


하지만 비동기에 대해서는 결과에 대한 기대가 명확하지 않습니다.


비동기 : 케이스 (002)


ex : ajax 에 대한 케이스가 가장 대표적일수 있습니다.


ajax로 특정 url에 대한 get을 요청 하였을 경우


// REST API 에 대한 테스트 케이스 로직을 짜는 경우



GET  /userInfo


$.ajax  ({

url : "127.0.0.1:8080/userInfo?userid=test_info

method:"GET",

success:function(res)

{

_before_api  = Array.prototype.slice.call(res.split('.'));

}

});


특정 url에 get요청을 하게되는데 id값을 보내서 해당 유저의 정보를 가져오는 작업에 대한 테스트 케이스를 작성하려고 할시에


백(서버) 에서 유저를 찾는데 오래걸리는 경우

서버에서 에러가 나는 경우

서버의 속도가 느린 경우



도대체 언제 해당 결과를 받을수 있는지

어떻게 받을수 있을지 -> error 코드를 받을수도 있고

해당의 경우에 테스트를 위해서는


비동기 테스트 로직을 짜야 한다.


동기 테스트에 경우는



getUserInfo = () => {return "testInfo"};



var expectValue = "testInfo";



getUserInfo===expectValue ? console.log("pass") : console.log("fail");






해당과 같이 기대값을 지정 하여서 assertion 을 진행할수 있지만


비동기의 경우는 위의 이유와 같이 언제 걸릴지도 모르고 결과가 일정하지 않습니다.



이렇기에 비동기 테스트를 짜기 위한 방식 및 테스트 코드 자체에서도 검증이 필요합니다.


우선 적으로 위의 ajax를 연속으로 확인한다고 해보겠습니다.



var testRunner = (function(){



var queue = [],paused=false, results;



// 멈춤

this.pause = function(){ paused= true;};

// 재 시작

this.resume = function(){ 

paused=false;  setTimeout(testMain,1);

 }



var testAssertion = function(testValue,testName){   // do it assertion };



// 스위트 이름 , 실행할 함수 (testsuite, fnc) 

var testFunction = function(testsuite,fnc)

{

queue.push(function(){
        fnc();

});



testMain();

};





var testMain = function()

{

if(!paused && queue.length)

{

queue.shift()();

if(!paused){ resume();}

}







};

return {

pause : pause,

resume : resume,

testFunction : testFunction,

};

})();



외부 접근 testRunner.testFunction("First Async",function(){









});





testRunner.testFunction("Second Async",function()

{

// 멈춤

testRunner.pause();



//비동기 코드 작성 ajax



$.ajax({

....

success:function(data)

{

// 시작

testRunner.resume();




}





});





});





생각나는대로 적어 봤는데 해당 코드는 대충 슈도 코드 정도로 보고


실제 테스트 를 하기 위한 테스트 모듈은 뒤에 만들어 볼 예정입니다.











Posted by 깍돌이

자바스크립트에서 함수가 선언되었을 경우 해당 함수가 글로벌하게 선언이 되어있을 경우 


자동적으로 브라우저의 window 객체에 이름과 함수가 선언이 된다.




[Chrome Console 창]

Posted by 깍돌이

children 과 childNodes 를 비슷해보이지만 결과값이 다르다



var child_array2 = window.document.getElementById("layout");

var nodes = child_array2.childNodes;

console.log(nodes);

nodes = child_array2.children;

     console.log(nodes);



사진을 보면 childNodes는 25개의 결과 가 나오지만  children 은 12개의 결과 가 나옵니다.


childNodes는  줄바꿈을 개수로 세는 경우가 있어서 해당과 같이 나옵니다.



자세한건 없고 되도록  children 을 쓰려고합니다.



'JavaScript > 끄적끄적' 카테고리의 다른 글

[JavaScript] 자바스크립트 문자열 개요  (0) 2018.04.02
1. Java Script 반올림  (0) 2017.11.21
Posted by 깍돌이

var round_i = 5555.55555555; 


console.log(round_i.toFixed(5));


 결과 : ->   5555.55556

'JavaScript > 끄적끄적' 카테고리의 다른 글

[JavaScript] 자바스크립트 문자열 개요  (0) 2018.04.02
2. childNodes, children  (0) 2017.12.04
Posted by 깍돌이
이전버튼 1 2 3 이전버튼

블로그 이미지
QA를 업으로 삼고 있습니다.
깍돌이

태그목록

Yesterday
Today
Total

달력

 « |  » 2025.2
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함