[textarea 리사이징]

사용자의 입력값에 따라 textarea 크기가 자동으로 조정되는 auto-resizing 기능이 있는 아래와 같은 textarea를 구현해보자.

1. 유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가/축소시킨다

2. 입력 가능한 라인 수(textarea 높이)는 제한한다

3. 입력시엔 textarea를 사용하고, 노출(읽기모드)시엔 textarea 대신 border가 없는 다른 tag를 사용한다

 

[구현에 필요한 사전지식]

1. HTML DOM element 와 jQuery Object

this 사용시 this가 jQuery Object 인지 DOM element 인지 명확히 구분해야 한다. (참고1, 참고2)

1. $(): jQuery Object
2. $var: jQuery 변수
3. $.each(function(){ 여기서 this는 DOM element }) 
4. jQuery Object에서 DOM element를 꺼내는 방법
- $(el).get(0)
- $(el)[0]

2. offsetHeight, clientHeight, scrollHeight 의 차이 (참고)

1. clientHeight : returns the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin
padding을 포함한 엘리먼트의 pixel 높이를 리턴, 가로스크롤바의 높이, border, margin 값은 포함하지 않음

2. offsetHeight : is a measurement which includes the element borders, the element vertical padding, the element horizontal scrollbar (if present, if rendered) and the element CSS height.
엘리먼트의 borders, 수직 padding 값, 가로 스크롤바(존재할경우)를 포함한 css 높이

3. scrollHeight : is a measurement of the height of an element's content including content not visible on the screen due to overflow
엘리먼트 내용물의 높이 (overflow로 보이지 않는 영역 포함)

3. textarea 의 문자열을 입력한 그대로(줄바꿈 형태 유지) 출력하는 방법

1) 출력시에도 textarea 를 그대로 사용

2) <pre> tag 혹은 줄바꿈/탭/자동줄바꿈 처리에 대한 white-space 속성 사용 

( 발췌 및 참고 : www.codingfactory.net/10597 )

  스페이스와 탭1 줄바꿈2 자동 줄바꿈3
normal 병합 병합 O
nowrap 병합 병합 X
pre 보존 보존 X
pre-wrap 보존 보존 O
pre-line 병합 보존 O

 

[구현]

1. CSS / HTML

noticeBox : 공지영역을 감싸고 있는 div

noticeTextarea : 작성모드에서의 textarea

noticeP : 읽기모드에서의 p태그. white-space:pre-wrap 속성을 주어 모든 스페이스/탭/줄바꿈에 대한 처리를 보존하고 자동 줄바꿈을 설정.

1
2
3
4
5
6
7
8
#noticeBox {display:none;}
#noticeTextarea {font-size:15px;
                margin-left:10px; 
                box-sizing: border-box; resize: none; border:1px solid #ccc; 
                vertical-align: center; box-sizing:border-box; 
                padding-left:12px; max-height:300px; /* overflow:hidden; */ /* width:95%; */
                }
#noticeP {font-size:15px; padding-left:50px; font-weight:bold; white-space:pre-wrap; width:95%;}
cs
1
2
3
4
5
6
7
8
9
10
11
<div id="noticeBox" class="contents">
    <div class="left_box">
        <span id="noticeLabel">공지</span><br>
        <span id="noticeCautionLabel" class="noticeAdminEle" style="color:red; font-size:8px;">(※500자 이하)</span><br>
    </div>
    <textarea id="noticeTextarea" class="noticeAdminEle" rows="2" cols="200" maxLength="500"><c:out value="${Notice.notice}"/></textarea>
    <p id="noticeP" class="noticeUserEle" ><c:out value="${Notice.notice}"/></p>
    <div class="right_box noticeAdminEle">
        <a href="javascript:noticeTextarea.upsertNotice();" class="redBtn">저장</a>
    </div>
</div>
cs

2. script document ready

var IS_NOTICE_AUTH = 공지사항작성권한 Y/N

공지사항작성권한 유무에 따라 Y는 textarea 사용, N 은 읽기모드로 textarea 대신 border 없는 tag 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script type="text/javascript">
var IS_NOTICE_AUTH = '<%=sample.SessionUtils.getIsNoticeAuth(request)%>';
 
$(document).ready(function() {
switch(IS_NOTICE_AUTH){
        case 'Y':
            //admin유저인 경우 화면처리
            noticeTextarea.editMode();
            
            //공지영역 리사이징
            noticeTextarea.addResizingEvtListener();
            noticeTextarea.initSizing();
            break;
        default:
            //일반 유저인 경우 화면처리
            noticeTextarea.readMode();
            break;
    }
})
</script>
cs

3. script function (참고)

1). noticeTextarea.addResizingEvtListener();

유저가 값을 입력했을 때 textarea 영역의 높이를 자동으로 증가시키기 위한 이벤트리스너(eventlistener)로 textarea에 keyup 이벤트에 걸어준다. 해상도가 정해진 환경에서 개발하므로 높이는 230으로 고정했으나 보다 정확한 라인 수 제한을 위해선 1줄짜리 textarea 를 생성한 후 높이값을 가져와 (높이 값 * 높이 제한 라인 수)로 maxHeight 를 뽑아 사용하는게 정확할 듯 하다.(1줄짜리 textarea는 사용자에겐 보이지 않게 hidden 처리)

 

2). noticeTextarea.initSizing();

최초 화면 로드시 textarea 영역 높이 조절. 이벤트 리스너를 걸어주고 $textarea.keyup(); 으로 강제로 이벤트를 호출해도 무방.

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var noticeTextarea = {
    //초기 로딩시 notice값 기준으로 textarea height 재조정
    initSizing : function(){
        var orgEle = $("#noticeTextarea")[0];
        var offsetOrgEle = orgEle.offsetHeight - orgEle.clientHeight;
        $(orgEle).css('height''auto').css('height', orgEle.scrollHeight + offsetOrgEle);
    } ,
    //resizing keyup 이벤트 걸기
    addResizingEvtListener : function(){
        var maxHeight = 230;
        $("#noticeTextarea").on('keyup input'function(e) {
            var offset = this.offsetHeight - this.clientHeight;
            if(this.scrollHeight + offset > maxHeight){
                //입력 가능 제한 줄 수 maxHeight 초과시, 가장 아랫줄 한글자씩 제거
                while(this.scrollHeight + offset > maxHeight) { 
                    $(this).val($(this).val().substr(0, $(this).val().length-1));
                    $(this).css('height''auto').css('height'this.scrollHeight + offset);
                } 
                alert("입력 가능한 줄 수가 초과되었습니다."); 
            }
            $(this).css('height''auto').css('height'this.scrollHeight + offset);
        });
    } ,
    //admin
    editMode : function(){
        $('#noticeBox').show();        //공지 영역 show
        $('.noticeUserEle').hide();    //user 영역 elements hidden
        $('.noticeAdminEle').show();//admin 영역 elements show
    } , 
    //user
    readMode : function(){
        $('.noticeAdminEle').hide();    //admin 영역 elements hide
        var noticeContents = $('#noticeP').text();
        noticeContents = noticeContents.replace(/\s|\r?\n|\r/g, '');
        if(noticeContents != null && noticeContents.length > 0){
            //공지 텍스트가 존재할 경우
            $('#noticeBox').show();    //공지 영역 show
            $('.noticeUserEle').show();//user 영역 elements show
        } else {
            $('#noticeBox').hide();    //공지 영역 hide
        }
    } , 
    upsertNotice : function (){
        if(confirm("공지를 저장하시겠습니까?")){
            //ajax 저장/수정 처리
        }
    }
}
cs

 

[결과]

1. 최초 화면에서의 textarea 크기

2. 엔터를 입력하여 늘어난 textarea 크기

3. 작성가능 유저가 아닌 일반유저에게 보이는 읽기전용 화면

 

[기타]

* 문자열 길이 제한 maxLength 사용시 주의사항 (참고)

특수문자 사용시 varchar2 기준 최대 3bytes 까지 차지할 수 있으므로 이를 고려하여 설계해야함.

ex) varchar2(1500) 으로 테이블 설계시 textarea maxLength 는 500자를 줘야함. (특수문자 3bytes * 500자 = 1500)

 

반응형

 

1. callback을 사용한 비동기 후처리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var callApi = function(successCallback, failCallback){
        $.post('/user.do', $("#parameter").serialize())
        .done(function(response){
              successCallback(response);
          })
        .fail(function(xhr, status, err){
               failCallback(err);                    
        });
     }
 
 
//on button click
callApi(function(data){
                  alert("this is successCallback!");
                  if(data.alertMssage !== undefined){
                    alert(data.alertMssage);
                  }
            },
            function(err){
                alert("this is failCallback!");
                alert(err);
            });    
cs

 

2. promise 를 사용한 비동기 후처리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var callApi = function(){
    return new Promise(function(resolve, reject){
                                $.post('/user.do', $("#parameter").serialize())
                                   .done((response)=>resolve(response))
                                   .fail((xhr, status, err)=>reject(err));
                               });
}
 
//on button click
callApi().then(function(data){
            alert("this is successCallback!");
            if(data.alertMssage !== undefined){
              alert(data.alertMssage);
            }
          }).catch(function(err){
              alert("this is failCallback!");
              alert("failed!");
          }); 
cs

 

promise에 대한 설명이 아래 링크에 워낙 잘 되어 있으므로 모든 설명은 생략.

설명이 매우 잘 되어있는 글

 

반응형

- 자바스크립트에서 원시 타입을 제외한 모든 나머지 값들(함수 배열 정규표현식 등)은 객체.
- 객체는 key 와 value 로 구성된 property 의 집합
- 프로퍼티 값이 함수인 경우 일반 함수와 구분하기 위해 메소드라 부름 (자바스크립트의 함수는 일급객체(참고)이므로 값으로 취급 가능)
- 객체는 데이터를 의미하는 프로퍼티와 데이터를 참조하고 조작할 수 있는 동작(메소드)로 구성된 집합
- 프로퍼티 및 메소드를 모두 포함할 수 있어 하나의 단위로 구조화하기 유용
- 프로토타입을 상속받아 객체지향의 상속을 구현한다

[프로퍼티]
- 프로퍼티 키를 중복 선언시 나중에 선언한 프로퍼티가 먼저 선언한 프로퍼티를 덮어씀
- 프로퍼티간 순서를 보장하지 않음

[메소드]
- 프로퍼티 값이 함수인 경우 메소드라 부름
- 객체에 제한되어 있는 함수를 의미

[객체 생성 방법]
1. 객체 리터럴
- 중괄호 사용하여 생성
- 비어있는 객체 생성 가능 ex) var empty = {};

1
2
3
4
5
6
7
var person = { 
    name : 'Lee'
    gender : 'male'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
cs

 

2. Object 생성자 함수
- new 연산자와 Object 생성자 함수를 호출하여 빈 객체 생성 가능
- 생성자 함수의 이름은 파스칼 케이스를 사용하는게 일반적
- 객체가 소유하고 있지 않은 프로퍼티 키에 값을 할당하면 해당 객체에 프로퍼티를 추가하고 값을 할당, 이미 존재하는 프로퍼티 키에 새로운 값을 할당하면 해당 값으로 변경
* Object 생성자 함수 사용보단 객체 리터럴 사용 (객체 리터럴 사용시 내부적으로 Object 생성자 함수를 사용하여 객체를 생성하므로)

3. 생성자 함수
프로퍼티 값만 다른 객체를 여러개 생성할 때 객체 리터럴 및 Object 생성자 함수를 사용한다면 아래와 같이 코드량이 많아지고 불편

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var person1 = { 
    name : 'Lee'
    gender : 'male'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
var person2 = { 
    name : 'Kim'
    gender : 'female'
    sayHello : function(){ 
        console.log('My name is' + this.name); 
    } 
cs

이를 아래와 같이 생성자 함수를 사용하면 간편

1
2
3
4
5
6
7
8
9
10
11
function Person(name, gender){ 
    this.name = name
    this.gender = gender; 
    this.sayHello = function(){ 
        console.log('Hi! My name is ' + this.name); 
    } 
var person1 = new Person('Lee''male'); 
var person2 = new Person('Kim''female'); 
person1.sayHello(); 
person2.sayHello(); 
cs

- 생성자 함수명은 대문자로 시작하여 생성자임을 인식하도록 도움을 줌
- 프로퍼티 또는 메소드 앞에 기술한 this는 생성할 인스턴스(비어있는 새로운 객체)를 의미(new 연산자와 함께 함수를 호출시 this 바인딩이 다르게 동작)
- this 에 바인딩되어있는 프로퍼티와 메소드는 외부에서 참조가 가능, 생성자 함수 내에서 선언된 일반 변수는 외부에서 참조 불가 : 생성자 함수 내부에서 자유롭게 접근이 가능하나 외부에서 접근은 불가 (아래 참고)

1
2
3
4
5
6
7
8
9
10
11
function Person(name, gender){ 
    var married = true
    this.name = name
    this.gender = gender; 
    this.sayHello = function(){ 
        console.log('Hi! My name is ' + this.name); 
    } 
var person = new Person('Lee''male'); 
console.log(person.gender); // 'male' 
console.log(person.married); // 'undefined' 
cs

※ 자바의 생성자와 다르게 형식이 정해져 있지 않고, 기존 함수와 동일한 방법으로 선언하고 new 연산자를 붙여 호출하면 생성자 함수로 동작
 생성자 함수가 아닌 일반 함수에 new 연산자를 붙일 경우 생성자 함수처럼 동작 가능하다는 것을 의미. 따라서 생성자 함수의 첫문자는 대문자로 명명하여 혼란 야기를 방지
new 연산자와 함께 함수를 호출하면 this 바인딩이 다르게 동작


[ new 연산자와 함께 생성자 함수 호출시 동작 순서 ]
1. 빈 객체 생성 및 this 바인딩 
- 생성자 함수의 코드가 실행되기 전 비어있는 객체가 생성된다
- 생성자 함수 내에서 사용하는 this 는 이 비어있는 객체를 가리킨다.
- 생성된 빈 객체의 프로토타입 객체는 생성자 함수의 prototype 프로퍼티가 가리키는 객체.
2. this를 통한 프로퍼티 생성
- 생성된 빈 객체에 this를 사용하여 프로퍼티나 메소드 생성 가능
3. 생성된 객체 반환
- this 에 바인딩된 객체 자동 반환


[ 객체 프로퍼티 선언 및 접근 ]
[ 프로퍼티 키 선언 ]
- 프로퍼티 키에 표현식(- 연산자 등)이 존재하는 경우 대괄호로 묶어야 함 otherwise, ReferenceError 발생, 예약어는 당연히 사용하면 안된다
ex: var person = {first-name : 'gildong'} >> ReferenceError

[ 프로퍼티 키 접근 ]
- 마짐표 . 표기법: 프로퍼티 키가 유효(표현식(- 연산자 등)이 있는 경우 무효), 예약어가 아닌 경우 마침표/대괄호 표기법 모두 사용 가능
- 대괄호 [] 표기법: 프로퍼티 키가 유효한 값이 아니거나, 예약어인 경우 대괄호 내에 들어가는 프로퍼티 이름은 반드시 문자열이어야 함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var person = { 
 'first-name''gildong'
  'last-name''Hong'
  gender: 'male'
  110 
console.log(person.first-name); // NaN : undefined - undefined  
console.log(person[first-name]); // ReferenceError 
console.log(person['first-name']); // 'gildong' 대괄호 표기법 대괄호 안이 반드시 문자열, 유효하지 않은 프로퍼티 키는 대괄호를 사용하여 읽음  
console.log(person.gender); // 'male' 유효한 프로퍼티 키는 대괄호, 마짐표 표기법 모두를 사용하여 읽기 가능 
console.log(person[gender]); // ReferenceError 
console.log(person['gender']); // 'male' 대괄호 표기법 대괄호 안이 반드시 문자열, 유효한 프로퍼티 키는 대괄호, 마짐표 표기법 모두를 사용하여 읽기 가능 
console.log(person['1']); //10 대괄호 표기법 대괄호 안이 반드시 문자열, 유효하지 않은 프로퍼티 키는 대괄호를 사용하여 읽음  
console.log(person[1]); //10 
console.log(person.1); //SyntaxError 
cs


[ 프로퍼티 값 수정 ]
- 객체가 갖고 있는 프로퍼티에 새로운 값 할당시 값이 수정됨 
ex) person.gender = 'female';

[ 프로퍼티 생성 ]
- 객체가 소유하고 있지 않은 프로퍼티 키와 값 할당시 새로운 프로퍼티 추가됨
ex) person.age = 30;

[ 프로퍼티 삭제 ]
- delete 키워드를 사용하여 객체 프로퍼티를 삭제, 이때 피연산자는 프로퍼티 키.
ex) delete person.gender;

[ 프로퍼티 값 출력 ]

1
2
3
4
5
6
for(var prop in person){ 
    console.log(prop + ':' +person[prop]); 
for(var idx in array){ 
    console.log(idx + ":" +array[idx]); 
cs

- for in문 사용하여 객체에 포함된 모든 프로퍼티 루프 출력이 가능
- for in문은 array 에서 사용을 삼가. 배열 요소만을 순회하지 않음
for of 사용 (ES6) 

[ pass by reference ]
객체 타입은 원시타입과 달리 동적으로 변화할 수 있으며 어느정도 메모리 공간을 확보해야 하는지 예측 불가하기 때문에 런타임에 메모리 공간을 확보하고 메모리의 힙영역에 저장된다. 

1
2
3
4
5
6
7
var foo = { 
    val : 10 
var bar = foo; 
console.log(foo.val, bar.val); // 10 10 
bar.val = 20
console.log(foo.val, bar.val); // 20 20 
cs

(위의 두 변수 모두 동일한 객체의 참조주소를 참조한다 (java의 참조객체와 동일))

참고 : https://poiemaweb.com/js-object#2-%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1-%EB%B0%A9%EB%B2%95

반응형

이상하게 라디오 관련 처리는 매번 할 때마다 바로바로 기억이 안나 정리해둔다.

 

[HTML]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul>
    <li>
        <input type="radio" id="type" name="type" value="1"><label for="type1">radio1</label>
        <input type="text" id="type_val" name="type_val" />
    </li>
    <li>
        <input type="radio" id="type" name="type" value="2"><label for="type2">radio2</label>
        <input type="text" id="type_val" name="type_val" />
    </li>
    <li>
        <input type="radio" id="type" name="type" value="3"><label for="type3">radio3</label>
        <input type="text" id="type_val" name="type_val" />
    </li>
</ul>
cs

 

[script]

1
2
3
4
5
6
7
8
9
$('input[type=radio][name=type]').change(function(){
    var arr = $('input[type=radio][name=type]');
    console.log($(this).val())
    for(var i=0; i<arr.length; i++){
        if($(this).val() != $(arr[i]).val()){
            $(arr[i]).siblings('input').val("");
        }
    }
});
cs

2번라인의 arr 은 radio 엘리먼트 배열이 들어가게 된다.

반복문을 돌려 this (현재 선택된 radio) 의 value 와 같지 않은 input value 는 비워준다.

※ 변수를 $() 로 감싸주면 javascript 변수가 jQuery 변수로 변환된다.

 

※ radio 버튼 강제 선택시키기

$("input:radio[name=radioGrp]:radio[value='U']").prop("checked", true);

참고

 

반응형

javascript 는 일부 에러를 무시하고 실행이 가능하다.

에러가 존재해도 동작한다는 이점이 있으나, 개발자의 디버깅을 더 힘들게 한다는 단점도 존재한다.

 

[ strict mode ? ]

ECMAScript5 에 추가된 기능으로써 에러를 더 엄격히 제한하는 기능.

사용법은 어렵지 않지만,

strict 사용시 기존에 묵인되던 에러들이 에러를 뿜게되니 관련부분은 나중에 정리.

 

참고 : https://www.geeksforgeeks.org/strict-mode-javascript/

 

반응형

1. 메소드 안 : 메소드를 소유한 object

this : object person

1
2
3
4
5
6
7
8
var person = {
  firstName: "John",
  lastName : "Doe",
  id     : 5566,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};
cs

 

2. alone(어디에도 속하지 않을 때?) : 전역 객체 (window)

1
2
3
4
<script>
var x = this;
document.getElementById("demo").innerHTML = x;
</script>
cs

 

3. 함수 안 : 전역 객체 (window)

1
2
3
4
5
6
<script>
document.getElementById("demo").innerHTML = myFunction();
function myFunction() {
  return this;
}
</script>
cs

 

4. 함수 안 (strict mode) : undefined

1
2
3
4
5
6
7
<script>
"use strict";
document.getElementById("demo").innerHTML = myFunction();
function myFunction() {
  return this;
}
</script>
cs

 

5. event 안 : event를 받는 element

this : button

1
2
<button onclick="this.style.display='none'">Click to Remove Me!</button>
 
cs

 

6. call(), apply() :  any object (그 어떤 객체도 의미 가능)

1
2
3
4
5
6
7
8
9
10
11
var person1 = {
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
}
var person2 = {
  firstName:"John",
  lastName: "Doe",
}
var x = person1.fullName.call(person2); 
document.getElementById("demo").innerHTML = x; 
cs

call(), apply() : https://www.zerocho.com/category/JavaScript/post/57433645a48729787807c3fd

 

출처 : https://www.w3schools.com/js/js_this.asp

 

 

 

반응형

[scope란?]

참조대상 식별자를 찾아내기 위한 규칙.

특정 변수가 선언되어 있을 때, 해당 변수를 소스 내 어디에서 찾아서 사용할 지를 규정하는 규칙.

 

[전역스코프 vs 지역스코프]

전역스코프 : 코드 내 모든 곳에서 참조 가능.

지역스코프 : 함수 코드 블록 내에서 만들어진 스코프로 함수 자기 자신과 하위 함수에서만 참조 할 수 있다.

※ 최상위 스코프는 window

 

[블록레벨스코프 vs 함수레벨스코프]

블록레벨스코프 block-level scope : if문, for문 과 같은 블록 내에 선언된 변수는 블록 밖에서는 참조가 불가하다. (대부분의 C언어, 자바언어)

함수레벨스코프 function-level-scope : 함수 코드 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 참조가 가능하다. (ECMAScript 6 부터 도입된 let 키워드 사용시 블록 레벨 스코프 사용 가능)

1
2
3
4
5
6
function sample(){
    if(true) {
        var tt = 1;
    }
    console.log(tt);
}
cs

>> javascript 는 함수레벨 스코프이므로, 함수 블록 내에서 선언된 변수는 함수 블록 내에서 참조가 가능. 싱기방기

1
2
3
4
5
6
function sample(){
    if(true) {
        let tt = 1;
    }
    console.log(tt);
}
cs

>> 블록레벨스코프 변수 let 을 사용했으므로 5번라인에서 tt 사용시 에러를 뱉음(java 및 기타 C계열언어와 같이 동작)

 

[동적스코프 vs 렉시컬스코프]

동적스코프 dynamic scope : 호출 시점에 따라 상위 스코프 결정

렉시컬스코프 lexical scope : 함수 선언 위치에 따라 상위 스코프 결정 (js 를 포함한 대부분의 언어가 해당 스코프를 따름)

1
2
3
4
5
6
7
8
9
10
var x = 1;
function foo() {
  var x = 10;
  bar();
}
function bar() {
  console.log(x);
}
foo(); // ?
bar(); // ?
cs

위와 같을 때, 결과는 1출력.

>> javascript 는 렉시컬 스코프를 따르므로 bar가 선언된 위치에 따라 상위 스코프가 결정되며, bar 내의 x 는 bar 의 상위 스코프 내에서 찾게된 전역 변수 x = 1 을 사용

※ 동적스코프 : bar의 상위 스코프는 함수 foo와 전역, 결과 10 출력

렉시컬스코프 : bar의 상위 스코프는 전역, 결과 1 출력

 

추가 예)

window.location.protocol 은 현재 페이지의 protocol (http: or https:) 을 뽑아낼 때 사용가능한 내장함수.

window 를 빼고, location.protocol 까지만 써줘도 window.location.protocol 을 가져올 수 있다.

스코프를 상위로 옮겨가며 탐색하다 계속 찾지 못한다면  window 까지 올라가서 찾아오기 때문.

 

그렇다면 protocol만 써줄 경우 이 케이스는 왜 못찾고 에러를 뱉는가?

> protocol은 window가 아닌 window.location 내에 존재.

> 현재 스코프 내에서 protocol 을 찾지 못한다면 상위 스코프에서 찾기 시작하고 결론적으론 window 까지 올라가서 찾게 될 뿐 window.location 내에서 찾진 않기 때문.

 

 

참고 : https://poiemaweb.com/js-scope

매우 좋은 블로그를 찾았다. 유레카..

반응형

javascript 에서 hoisting 이란 단어 뜻 그대로 끌어올리기라는 의미로써, 변수를 최상단으로 끌어올리는 것을 뜻한다.

이와 같은 자바스크립트에서의 호이스팅이란 특징으로 인해, 

javascript에서 변수는 사용된 이후 선언 될 수 있다. (==변수를 사용한 후 선언 할 수 있다)

 

[case 1]

1
2
3
4
5
$(document).ready(function(){
    var x;
    x = 5;
    console.log(x);
});
cs

변수를 선언 후 변수에 값을 저장한 케이스. 보기에도 문제가 없어보이고 실행 결과도 문제가 없다.

[case 2]

1
2
3
4
5
$(document).ready(function(){
    x = 5;
    console.log(x);
    var x;
});
cs

변수에 값을 저장/사용 후 선언한 케이스

java 같으면 케이스2에서 Exception 을 뱉겠지만, javascript 는 결과 5를 정상적으로 console 에 출력한다.

보기엔 에러가 발생할 것으로 보였던 코드임에도 에러없이 정상 결과가 나온 이유는 바로 hoisting 때문이다.

(var x; 부분(변수 선언부)을 현재 scope에서 최상단으로 끌어올렸기 때문)

(스코프와 관련된 내용은 여기를 참고)

 

그렇다면 호이스팅은 항상 이뤄질까?

자바스크립트는 선언부만 hoisting 할 뿐, 초기화 부분까지 호이스팅하지 않는다.

[case 3]

1
2
3
4
5
$(document).ready(function(){
    console.log(x);
    console.log(y);
    var x = 5;
});
cs

 

위 샘플 소스의 결과는 아래와 같다.

x 는 'undefined'를 콘솔에 출력하고 있고,

y 는 undefined Error 을 던지고 있다.

var x 부분은 hoisting 되었지만 초기화(=5)부분은 호이스팅되지 않았기 때문이다.

y는 스코프내에 선언되어 있지 않으므로 Error 를 뱉고 있다.

[결론]

예상치 못한 hoisting 동작으로 인한 에러를 피하기 위해 변수 선언 및 초기화는 최상단에서 해주자.

 

 

참고 : https://www.w3schools.com/js/js_hoisting.asp

 

 

반응형

typeof 는 js에서 타입을 반환하는 연산자(operator)로써 변수의 타입을 확인할 때 사용한다.

 

typeof 로 아래와 같이 number, string, object, boolean, function 타입을 확인 할 수 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log(typeof 123);              //number
console.log(typeof "str");             //string
console.log(typeof new Object());      //object
console.log(typeof {test : "test"});   //object
console.log(typeof true);              //boolean
console.log(typeof Symbol());          //symbol
console.log(typeof function(){});      //function
 
console.log(typeof 123 === 'number');               //true
console.log(typeof "str" === 'string');             //true
console.log(typeof new Object() === 'object');      //true
console.log(typeof {test : "test"=== 'object');   //true
console.log(typeof true === 'boolean');             //true
console.log(typeof Symbol() === 'symbol');          //true
console.log(typeof function(){} === 'function');    //true
cs

 

다음과 같은 타입은 주의하여 사용하자.

1
2
3
4
5
6
7
8
console.log(typeof null);                    //object
console.log(typeof new Object(123));        //object
console.log(typeof new Object("123"));        //object
        
console.log(typeof null === 'undefined');                //false
console.log(typeof new Object(123=== 'object');        //true
console.log(typeof new Object(123=== 'number');        //false
console.log(typeof new Object("123"=== 'string');        //false
cs

1. null 은 object (null 은 != null 과 같이 체크 할 것)

2. Object에 담긴 number/string 는 object

 

undefined : 선언은 되어있으나 아무 값도 저장되어 있지 않은 경우

undeclared : 변수 선언 자체가 되어 있지 않은 경우

* undefined , undeclared 모두 typeof 시 undefined로 반환

 

 

참고 : 

typeof document

정리가 잘 되어있는 글 (영어)

정리가 매우 잘 되어있는 글(한글)

반응형

javascript 에서 함수는 1급객체이다.

javascript 에서 함수는 아래와 같은 특징을 지닌다.

 

1. 익명함수로 작성 가능

2. 리턴값으로 사용 가능

3. 매개변수로 사용 가능

4. 변수, 자료구조로 저장 가능

 

위와 같은 특징으로 인해 callback 함수 같은 개..념이 존재.

 

[함수 선언식 vs 함수 표현식]

함수 선언식 : function func(){}

함수 표현식 : var func = function(){}

 

함수선언식으로 소스를 작성해도, 해당 소스 구동시 js 엔진 내에서 함수선언식을 함수표현식으로 바꾼다.

반응형

+ Recent posts