2014.11.12 23:27

JavaScript Quiz


Quiz 1
var name = "javarouka";
var introduce = function() {
    var intro = "My name is ";
    if(!name) {
        var name = "unknown"
    }
    return intro += name;
}
document.write(introduce());
  • "My name is undefined"
  • "My name is null"
  • "My name is javarouka"
  • "My name is unknown”
    : function scope에 선언된 variable name은 introduce 함수 실행 시 hoisting 되어 undefined로 초기화 된 상태가 되므로 if(!name) 구문 내부로 진입이 가능하게 된다.
    또한, local variable로 선언된 name이 “unknown”값으로 할당을 받으면  global scope에 선언된 name은 shadow 되므로 “javarouka”가 아닌 “unknown”이 최종 값이 된다


Quiz 2

document.write(myName() + " / ");
var myName = "javarouka";
function myName() {
    return "rouxrouka";
}
delete myName;
document.write(myName);
  • 실행 오류
  • "rouxrouka / javarouka”
    :  myName과 같은 Named Function은 script loading과 동시에 AST에 구성되어 Hoisting과 더불어 선언이 완료된다. 따라서, 초기 myName을 호출해도 정상 동작하게 되어 “rouxrouka”값을 얻게 된다.
    이후 var로 myName을 재선언 하게 되면 myName은 함수가 아닌 문자열 object로 인식하게 된다. 이후 delete를 호출하여 myName을 삭제 하려하고 있으나 var로 선언된 myName은 삭제 불가 속성이므로 삭제되지 않고 “javarouka” 값을 유지하게 된다.
  • "undefined / javarouka"
  • "undefined / undefined"


Quiz 3

(function(doc) {
    document.write(new doc() === doc());
    document.write(new doc() === document);
    document.write(doc() === document);
})
(function arg() {
    return document;
})
  • 실행 오류
  • "falsefalsefalse"
  • "falsefalsetrue"
  • "falsetruetrue"
  • “truetruetrue” 
    : 위의 구조는 IIFE 방식으로 arg() 함수가 doc으로 넘겨지는 구조를 가진다. JavaScript에서는 new 키워드를 하여 함수를 constructor로 인식 object를 생성 할 수 있다.
    new operation을 실행하면 먼저 메모리 공간에 empty object를 생성하고 이 object의 constructor property를 constructor 함수의 저장 영역을 가리키게 한 후 constructor 함수를 호출하면서 context를 새로 생성된 object로 bind하게 된다. constructor 함수의 실행이 종료되면 생성된 object (this) 를 return하게 되는데, 만약 constructor 함수가 임의의 object를 명시적으로 return 하는 경우 새로 생성한 object 대신 명시된 object를 return 하게 된다.

    JavaScript의 이러한 특징에 의해 예제의 new doc()과 doc()을 실행하여 얻는 object는 document로 identical 조건을 만족한다. 만약, return값이 object가 아닌 string과 같은 literal일 경우는 해당되지 않으므로 결과 값은 falsefalsetrue가 된다.

    참고로, 이러한 constructor 함수의 특징을 이용하여 private function 을 구현 하기도 한다.
  • "truefalsefalse"
  • "truetruefalse"


Quiz 4

function setter(aryUnits) {
    for(var i=0; i < aryUnits.length; i++) {
        var id = i + 1;
        aryUnits[i] = new Object();
        aryUnits[i].getId = function() {
            return id;
        }
    }
}
var ary = new Array(5);
setter(ary);
document.write(ary[3].getId());
  • 실행 오류
  • undefined
  • 4
  • 5
    : setter 함수의 for loop 에서 var 로 선언된 id는 hoisting되어 setter 함수의 진입 시 undefined 값을 가지게 된다.
    aryUnits element에 할당하는 getId 정보는 단지 Function Literal로 for loop을 통해 함수 자체가 실행되는 것이 아니며, 이후 getId()를 호출 하는 시점에 scope이 형성된다. 이 함수의 내부에서 사용되는 id는 setter 함수 scope에 bind된 id로서 reference만 유지하게 된다.

    이 예제에서는 for loop이 진행되면서 id는 1에서 5까지 변하게 되지만 array별로 할당받은 getId 함수를 호출할 때는 결국 같은 object인 id를 참고하게 된다. 따라서, id의 최종 id 값인 5를 얻게 된다.

    각 array element 별로 값을 얻기 위해선 id를 얻는 function을 closure로 생성하여 scope을 확보 후 넘겨 주어야 한다.
    getId = (function(id) {
        return function() {
            return id;
        }
    })(id);


Quiz 5

function args() {
    return (typeof arguments) && (arguments instanceof Array);
}
document.write(args());
  • 실행 오류
  • "object"
  • true
  • false
    : typeof arguments는 object이나 arguments는 Array Like Object이므로 Array Instance가 아니다


Quiz 6

var c;
document.write(typeof typeof c);
  • "undefined"
  • "object"
  • 실행 오류
  • “string” 
    : typeof c는 “object”라는 string literal 값을 가지므로 typeof “object”는 “string”이 된다.


Quiz 7

var privacy = {
    secret: "I did not study last night.",
    getSecret : function() {
        return this.secret;
    }
};
var what = privacy.getSecret;
document.write(what());
  • 실행 오류
  • "I did not study last night."
  • undefined
    : privacy.getSecret 함수를 global variable인 what에 할당을 한 경우이므로, 실제 함수가 실행 될 때 this는 what이 속해 있는 window object를 context로 인식하게 된다. window에는 secret이 정의 되어 있지 않았으므로 undefined 값을 얻게 된다. 만약, var secret = “100”으로 global variable을 설정한 경우라면 당연히 return 되는 값은 “100”을 얻게 된다. 또한, what()이 아닌 privacy.getSecret()을 실행하면 this는 privacy object가 되므로 “I did ~~ night.” 값을 얻게 된다.

    JavaScript의 Function에서 기본적으로 제공하는 기능 중에 call이나 apply의 경우 이러한 context를 다르게 줄 수 있는 기능을 제공한다. 예를 들어 what.call(privacy)라고 호출 했다면, 비록 what이라는 함수를 실행한다해도 context가 privacy이므로 “I did ~~ night”를 호출하게 된다.
  • "function() { return this.secret; }"


Quiz 8

function func1( ) { return func1; }
if(new func1() === func1()) {
    document.write("same!");
}
else {
    document.write("different!");
}
  • 실행 오류
  • "same!”
    : 앞서 Quiz3번과 유사한 문제로 초기 AST(Abstract Syntax Tree)구성 시 f
    unc1이 Named Function으로 등록된다. 그 상태에서 new func1()을 실행하면 return 값으로 func1 함수 object을 return하고 func1()을 실행 할 때도 마찬가지로 동일한 func1을 얻게 된다.
  • "different!"


Quiz 9

(function(){
    Object.prototype.scope = "prototype";
    (function(f) {
        var scope = "local";
        alert(f());
    })(function checkScope() { return scope; });
})();
  • 실행 오류
  • "local"
  • “prototype” 
    : Object.prototype.scope에 값을 assign하는 경우 모든 Object에 scope이라는 property key를 갖게 된다. IIFE 함수의 argument로서 넘겨받은 checkScope 함수를 실행하면 IIFE의 context에 bind되므로 scope == window.scope을 의미하게 된다. 따라서, global로 scope이 정의되어 있지 않아 undefined가 될 것 같은 모습이지만, 앞서 Object의 prototype에 scope이라는 property를 추가 해 주었기 때문에 prototype chain을 따라 그 값은 “prototype”이 된다. 

     만약,
    var scope 대신 scope = “local” 또는 this.scope = “local” 이라고 선언 했다면, 명시적으로 window.scope에 값이 할당된 것이므로 prototype 값이 아닌 window object에 할당된 메모리 영역을 접근하여 “local” 값을 얻게 된다.
  • "undefined"


Quiz 10

var strZero = "0";
var numZero = 0;
var notNumer = NaN;
var strEmpty = '';
var tab = '\t';
var undef;
var nll = null;
if(strZero == true) {
    document.write("1");
}
if(notNumer == false) {
    document.write("2");
}
if(undef == nll) {
    document.write("3");
}
if(tab == 0) {
    document.write("4");
}
if(tab == true) {
    document.write("5");
}
if(strEmpty == numZero) {
    document.write("6");
}
if(false == 'false') {
    document.write("7");
}
if(strEmpty == false) {
    document.write("8");
}
  • ""
  • "78"
  • “3468” :
    1: 문자열 “0”과 boolean의 비교 이므로 strZero는 0 true은 1로 비교하므로 false
    2: NaN은 어떤 값과 비교해도 false
    3: undefined와 null은 abstract equality comparison에서 같은 것으로 인식하므로 true
    4: 문자열 number 비교로 문자열 tab을 숫자 0으로 변환되므로 true

    5: 문자열 boolean 비교로 문자열 tab을 숫자 0으로 변환되고, true는 1로 변환되므로 false
    6: 문자열 number 비교로 strEmpty는 숫자 0으로 변환되므로 true
    7: 문자열 boolean 비교로 false는 +0으로 변환되고 ‘false’는 numeric literal이 아니므로 변환되지 않으므로 false
    8: 문자열 boolean 비교로 false는 +0으로 변환되고 strEmpty는 숫자 0으로 변환되므로 true

    JavaScript 비교 연산에 대한 정리는 JavaScript Equality Operator 에 대한 글을 참고하기 바란다.
  • "34568"
  • "2567"


'Technical Stubs > JavaScript' 카테고리의 다른 글

JavaScript Quiz  (0) 2014.11.12
JavaScript 비교 연산에 대한 정리  (0) 2014.11.12
Trackback 0 Comment 0
2014.11.12 23:04

JavaScript 비교 연산에 대한 정리

JavaScript 비교 연산에 대한 정리

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators 에 정리된 글을 참고하였음.


요약 정보

  • 글자에 대한 시퀀스, 길이 및 각 위치에 대해 동일한 문자가 있는 경우 같은 문자열로 본다.
  • 숫자의 값이 동일할 때 두 숫자는 같은 것으로 본다.
    NaN (Not a Number)는 NaN을 포함하여 어떤 것과도 같지 않다.
    양의 0과 음의 0은 서로 같은 것으로 본다. 
  • 두 개의 boolean 대상이 둘 다 true 거나 false인 경우만 서로 같은 것으로 본다
  • 두 개의 구분되는 object는 strict 또는 abstract 비교 시 절대 같지 않아야 한다
  • Object를 비교하는 expression은 서로 참고하는 object가 같은 경우에만 true이다.
  • Null과 Undefined 타입은 strict 비교시는 Null은 Null과 Undefined는 Undefined 만 서로 같을 수 있으나,
    abstract 비교시에는 Null과 Undefined는 서로 같을 수 있다. 

Equality (==)

  • equality operator는 서로의 타입이 다를 경우 타입을 자동으로 변환 후 strict 비교를 한다
  • 대상이 number 또는 boolean 타입 중 하나일 경우 모든 대상을 number 로 변환 후 비교한다. (단, 변환이 가능 할 경우에만)
  • 대상이 string 일 경우라면 숫자형로 변환이 가능할 경우 number로 변환 후 비교한다.
  • 대상이 둘 다 object 라면 각 object가 참고하는 내부 메모리 공간이 동일한지 비교한다.

Identity (===)

  • identity operator는 타입과 상관 없이 strict 비교를 한다.

Comparison Algorithm


Abstract Equality Comparison에서 Type 변경이 발생하는 경우 다음과 같은 규칙을 따른다.

  • number와 string을 비교시, string은 number 값으로 변환된다.
    JavaScript는 string numeric literal을 Number 타입 값으로 변환을 시도하게 된다.
    먼저, 수학적인 값이 string numeric literal 로 부터 얻어지게 되고, Number 값에 가장 가까운 값으로 반올림 또는 버림된다.
  • 만약 대상 중 하나가 Boolean 인 경우, 이 Boolean이 true 몇 1 false면 +0 값으로 변환된다.
  • 만약 object가 number나 string으로 비교되는 경우, JavaScript는 object의 기본 값을 return 하는지 시도하게 된다. object의 valueOf나 toString 메소드를 이용해서 Number 값이나 String과 같은 primitive 값으로 변환을 시도를 한다. 만약, object 변환에 실패하면 runtime error를 생성한다.
  • Object가 primitive 값으로 변환되는 경우는 그 비교 대상이 오직 primitive 타입일 경우에만 변환되며, 대상이 둘 다 object 일 경우는 각각의 object가 같은 memory를 참고하는지에 대한 비교만 하게된다.

Abstract Equality Comparison 예제

  • 1 == ‘1’
    true : number - string 비교이며 string ‘1’이 number 1로 변환 후 비교
  • 1 == true
    true : boolean 비교이므로 true는 1로 변환 후 비교
  • ‘1’ == true
    true : boolean 비교이므로 true는 1로 변환되며 string ‘1’은 number 1로 변환되어 비교
  • ‘2’ == true
    false : boolean 비교이므로 true는 1로 변환되나 string ‘2’는 number 2로 변환되어 비교 
  • new Number(0) && new Boolean(false)
    true : new Number(0)는 number 0에 대한 object이므로 number 0과는 다름.
    Equality 를 비교를 위해서는 다음과 같이 풀어서 사용해야 함
    new Number(0) == true && new Boolean(false) == true
  • ‘ ‘ == 0
    true : number - string 비교이므로 string ‘ ‘이 number 0으로 변환 후 비교
  • NaN == NaN
    false : NaN은 그 어떤 것과 비교해도 false
  • null == undefined
    true : null은 undefined와 비교 시 같은 것으로 취급된다.
  • null == 0
    false : null은 undefined나 null과의 비교에서만 true가 된다.

if 문에서 true 조건

  • if statement condition은 해당 값이 0, false, null, undefined, NaN이 아닌 경우 true로 인식한다.


'Technical Stubs > JavaScript' 카테고리의 다른 글

JavaScript Quiz  (0) 2014.11.12
JavaScript 비교 연산에 대한 정리  (0) 2014.11.12
Trackback 0 Comment 0