반응형
반응형

출처: https://okky.kr/article/409329


추상화, 의존성 분리, 캡슐화 등등... 말은 참 쉽지만 실전에서 와닿기 힘들 수 있습니다.

자바스크립트로 [Button]을 눌렀을 때 [Text]에 버튼을 누른 횟수를 표시하는 코드를 모델링해보겠습니다. (객체를 설계해보겠습니다.)


1. 어설픈 모델링


class Text {
  constructor(){
    this.view = document.createElement('div');
    this.view.textContent = "[0]";
    document.body.append(this.view);
  }
}

class Button {
  constructor(){
    this.view = document.createElement('button');
    this.view.textContent = "INCREMENT";
    document.body.append(this.view);

    this.clicked = 0;
    this.view.onclick = () => {
      text.view.textContent = `[${this.clicked++}]`;
    }
  }
}

let text = new Text();
let button = new Button();


위 코드는 잘 작동하지만 Button을 사용하기 위해서는 다음과 같은 의존성이 있습니다.

  • 전역 스코프에 text라는 객체가 있을 것
  • text는 view라는 객체를 속성으로 가질 것
  • text.view는 textContent라는 String을 속성으로 가질 것

혹은

  • 전역 스코프의 text라는 객체가 있을 것
  • text는 view라는 HTMLElement를 속성으로 가질 것

이 때문에

let text = new Text();
let button = new Button();

위 코드를

let button = new Button();
let text = new Text();

이렇게만 바꿔도 작동하지 않으며, 현실적으로 재사용하고 확장하기에 무리가 있습니다.


2. 추상화

  • 전역 스코프에 text라는 객체가 있을 것
  • text는 view라는 객체를 속성으로 가질 것
  • text.view는 textContent라는 String을 속성으로 가질 것

이 세가지 항목을 최대한 줄여볼 수 있을까요?
전역 스코프 사용을 자제하고, 모델을 약간 추상화해보겠습니다.

class Text {
  constructor(){
    this.view = document.createElement('div');
    document.body.append(this.view);
    this.render(0);
  }

  render(number){
    this.view.textContent = `[${number}]`;
  }
}

class Button {
  constructor(text){
    this.view = document.createElement('button');
    this.view.textContent = "INCREMENT";
    document.body.append(this.view);

    this.clicked = 0;
    this.view.onclick = () => {
      text.render(this.clicked++);
    }
  }
}

let text = new Text();
let button = new Button(text);


이런 방식으로 의존성이 줄어들 수 있겠습니다. 위 코드에서 Button의 의존성은

  • 생성자의 인자가 render(Number)를 속성으로 갖는 객체 일 것

의존성을 줄이려다보니, Text에 render라는 메소드를 만들게 됐습니다.
화면에 보이는 결과는 같지만 의존성이 줄었을뿐만 아니라, Text의 모습을 제어하는 코드 역시 자연스럽게 Text에 캡슐화가 되었습니다.


// 의사 코드
interface Renderable {
  void render(Number number);
}

class Button {
  constructor(Renderable renderer){
    // ...
  }
}


JS가 정적 타입 언어라면, 위처럼 Text의 생성자에 좀 더 제약사항을 걸어서 코드의 안정성과 가독성을 높힐 수도 있겠습니다.

이렇게 Renderable이라는 추상계층을 통해서 의존성을 줄일 수 있습니다.


3. 확장성

의존성이 단순하기 때문에 Button의 역할을 확장하기가 수월합니다.

새로운 요구사항

  • Button에 Renderable한 객체들을 여러개 연결하고 싶음


class Text {
  // ...
}

class Balls {
  constructor(){
    this.view = document.createElement('div');
    document.body.append(this.view);
  }

  render(number){
    this.view.innerHTML = '';
    for(let i=0; i<number; i++) {
      let ball = document.createElement('div');
      ball.style.background = 'orange';
      ball.style.width = ball.style.height = '1em';
      ball.style.borderRadius = '50%';
      ball.style.display = 'inline-block';
      this.view.appendChild(ball);
    }
  }
}

class Button {
  constructor(renderers){
    this.view = document.createElement('button');
    this.view.textContent = "INCREMENT";
    document.body.append(this.view);

    this.clicked = 0;
    this.view.onclick = () => {
      this.clicked++;
      renderers.forEach(renderer => renderer.render(this.clicked));
    }
  }
}

let text = new Text();
let balls = new Balls();
let button = new Button([text, balls]);


이렇게 해서 Button은 여러 Renderable과 느슨하게 결합 할 수 있습니다.

이제 Button의 의존성은 (엄밀하게 말하면 의존성은 Renderable 인터페이스 뿐입니다)

  • 생성자 인자의 타입은 Array<Renderable> 일것

4. 동적인 참조

그런데 아직도

let text = new Text();
let balls = new Balls();
let button = new Button([text, balls]);

let button = new Button([text, balls]);
let text = new Text();
let balls = new Balls();

로 바꿀 수는 없는 점이 아쉽습니다.

새로운 요구사항

  • Button을 생성하는 시점이 아니라, 생성된 이후에도 Button에 Renderable들을 연결하고 싶음


class Text {
  // ...
}

class Balls {
  // ...
}

class Button {
  constructor(renderers = []){ // 기본값을 할당하는 코드입니다.
    this.view = document.createElement('button');
    this.view.textContent = "INCREMENT";
    document.body.append(this.view);

    this.clicked = 0;
    this.renderers = renderers;
    this.view.onclick = () => {
      this.clicked++;
      this.renderers.forEach(renderer => renderer.render(this.clicked));
    }
  }

  connect(renderer){
    this.renderers.push(renderer);
  }
}

let text = new Text();
let button = new Button([new Balls()]);
button.connect(text);


이제 Button에 동적으로 Renderable들을 연결 할 수 있습니다.


5. 의존성 없애기!

Button이 Renderable들의 render 코드를 호출하는 대신에,
이벤트 주도(감시자 패턴, 출판-구독 패턴..) 방식으로 Renderable이라는 제약사항을 없앨 수도 있습니다.

새로운 요구사항

  • Balls, Text을 Renderable에서 탈피시키며 의존성을 완전히 없애기


class Text {
  constructor(){
    this.view = document.createElement('div');
    document.body.append(this.view);
    this.number = 0;
    this.count();
  }

  count(){
    this.view.textContent = `[${this.number++}]`;
  }
}

class Balls {
  constructor(){
    this.view = document.createElement('div');
    document.body.append(this.view);
  }

  generate(){
    this.view.innerHTML = '';
    let number = Math.floor(Math.random()*10);
    for(let i=0; i<number; i++) {
      let ball = document.createElement('div');
      ball.style.background = 'orange';
      ball.style.width = ball.style.height = '1em';
      ball.style.borderRadius = '50%';
      ball.style.display = 'inline-block';
      this.view.appendChild(ball);
    }
  }
}

class Button {
  constructor(text){
    this.view = document.createElement('button');
    this.view.textContent = text;
    document.body.append(this.view);

    this.clickHandlers = [];
    this.view.onclick = () => {
      this.clicked++;
      this.clickHandlers.forEach(handler => handler(this.clicked));
    }
  }

  addClickHandler(handler) {
    this.clickHandlers.push(handler);
  }
}

let balls = new Balls();
let text = new Text();

// increment button
let button = new Button("INCREMENT");
button.addClickHandler(() => {
  text.count();
});

// button for both
let button2 = new Button("CLICK ME");
button2.addClickHandler(() => {
  balls.generate();
  text.count();
});


이제 Button은 인스턴스별로 원하는 hook(callback, handler, listener, observer 등..)을 등록하여 입맛대로 쓸 수 있습니다.

* 아시는 것처럼 DOM에는 당연히 native로 각종 이벤트 핸들러를 부착할 수 있습니다, JS를 예시로 들다보니 같은 작업을 중복한 꼴이 되었습니다만, 지금 예시로 든 GUI 뿐 아니라 그 어떤 코드에서도 의존성에서 탈피하기 위해서 같은 원리를 적용 할 수 있음을 말하고자 합니다.


맺음말.

의존성에서 벗어나야 좋은 코드라는데, 위 처럼 의존성이 하나도 없는게 최고군요!

  • 의존성이 없으면 그만큼 확장성이 있지만, 원하는 대로 그 쓰임새를 강제 할수가 없습니다.

예를 들어서 현금,부동산 등을 등록 할 수 있는 회계사가 있다고 해봅시다.
회계사는 현금부동산과 현금으로평가할수있는 인터페이스로 느슨하게 연결되어 있습니다.


interface 현금으로평가할수있는 {
  금액 현금으로평가();
}


이를 통해서 회계사는 현금이나 부동산 등을 현금으로 평가하여 다룰 수 있습니다. 또한 비트코인이라는 새로운 객체에도 현금으로평가할수있는이라는 명시적인 인터페이스만 구현해준다면 쉽게 회계사와 연결 할 수 있습니다.

이렇게 적절한 의존성을 통해서 쓰임새의 방향을 어느 정도 강제하고, 확장의 가이드가 될 수 있습니다.

---

디자인 패턴을 공부해도 막상 실제 코드엔 적용하기가 쉽지 않습니다. 저는 코드의 구조에 그 합당한 이유가 있어야 한다는 생각을 합니다. 아무런 필요도 준비도 없이, 디자인패턴들을 되새김질하며 마치 공식처럼 적용하려고 하기보다는, 재사용, 확장성, 추상화의 키워드를 핵심 컨셉으로 "필요에 따라서 리팩토링" 해나가면 좋겠습니다.

반응형
반응형
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
function isValidPassword(pwd){
    var alpaBig= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var alpaSmall= "abcdefghijklmnopqrstuvwxyz";
    var num = "01234567890";
    //널인지?
    if(isEmpty(pwd)){
        return null;
    }
    // 비밀번호는 6자리이상 8자리 이하 .. maxLength=10로 변경 할것
    if(getByteLength(pwd)<6 || getByteLength(pwd) > 10 ){
        ERR_MSG = "비밀번호는 반드시 6자 이상 8자이내로 입력해야 합니다.";
        return false;
    }
    if(isNum(pwd)){
        ERR_MSG = "비밀번호는 반드시 알파벳을 하나 이상 포함해야 합니다.";
        return false;
    }
    for(var i=0;i < alpaBig.length - pwd.length+1;i++){
        if(alpaBig.substring(i,i+pwd.length== pwd)
        {
            ERR_MSG = "ABCDEF처럼 연속된 문자는 사용할 수 가 없습니다.";
            return false;
        }
    }
    if (pwd.indexOf(' '> -1) {
        ERR_MSG = "공백은 입력할 수 없습니다.";
        return false;
    }
    for(i=0;i < alpaSmall.length - pwd.length+1;i++){
        if(alpaSmall.substring(i,i+pwd.length== pwd)
        {
            ERR_MSG = "abcdef처럼 연속된 문자는 사용할 수 가 없습니다.";
            return false;
        }
    }
    for(i=1;i < pwd.length;i++){
        if(pwd.substring(0,1!= pwd.substring(i,i+1) )
            return true;
    }
    ERR_MSG = "비밀번호는 같은 문자만 연속해서 입력할 수 없습니다";
    return false;
}
 
// 숫자만 사용했는지 체크
function isNum(str){
    if(isEmpty(str)) return false;
    for(var idx=0;idx < str.length;idx++){
        if(str.charAt(idx) < '0' || str.charAt(idx) > '9'){
            return false;
        }
    }
    return true;
}
 
// 빈값인지 아닌지 판단
function isEmpty(pValue){
    if( (pValue == ""|| (pValue == null) ){
        return true;
    }
    return false;
}
 
출처: http://xepi.tistory.com/entry/비밀번호-검증-스크립트-연속된-문자같은문자-반복-등 [xepi'z dev note]
cs


나중에 사용할일이 있을거같아서 저장

반응형
반응형

숫자형식의 값을 화면에 보여줄때에는 화폐단위처럼 숫자 3자리마다 콤마(comma)를 추가해주면 가독성이 좋아진다.

프로그래밍 언어별로 이러한것을 처리하기 위해 숫자를 특정 형식대로 포맷팅 해줄수가 있는데, 자바스크립트는 그러한 기능이 없다. 물론 우리들이 흔하게 사용하년 jQuery에도 그러한 기능은 없다. (jQuery는 숫자형식을 컨트롤 하는 플러그인이 있다)

그렇기 때문에 숫자를 화페단위처럼 3자리마다 콤마를 넣어주긴 위해선 해당 기능을 하는 함수를 만들어서 사용해야 한다.

일반적으로 인터넷에서 검색했을때 제일 많이 나오는 함수는 아래와 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function comma(num){
    var len, point, str; 
       
    num = num + ""
    point = num.length % 3 ;
    len = num.length
   
    str = num.substring(0, point); 
    while (point < len) { 
        if (str != "") str += ","
        str += num.substring(point, point + 3); 
        point += 3
    } 
     
    return str;
 
}
 
cs



위의 함수의 경우 나와 같이 일을 하는 막내직원이 어디선가 긁어와서 사용중인 함수인데, 위와 같이 while문을 통해
자릿수마다 콤마를 추가하고 있다. 

위 방법보다는 공백제거 함수처럼 정규식을 사용할수 있지 않을까 해서 검색해보니 stackoverflow에 떡하니 있다 !!



1
2
3
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
cs



심플하다 !!


참고

http://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript

http://fruitdev.tistory.com/160#comment14445226

반응형
반응형

질문글중에 이런코드가 있었다


-HTML 단

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<tr>
  <td id="title">
      <input class="input" type="text" id="nameEdit4" name="nameEdit4" value="123">
      <input xlass="input" type="hidden" id="fileData1" name="fileData" value="170620_검토중.xlsx">
      <input class="input" type="hidden" id="fileData2" name="fileData" value="error.txt">
      <input class="input" type="hidden" id="fileData3" name="fileData" value="">
      <input class="input" type="hidden" id="fileData4" name="fileData" value="">
      <input class="input" type="hidden" id="fileData5" name="fileData" value="">
      <span class="value" value="">123</span>
  </td>
  <td>
    <div class="tools">
      <a class="modal detail-btn" href="#" data-modal-index="1"  >
      <i class="icon popup icon-22px lightblue" id="icon4" onclick="myFunction(this)"></i></a
    </div>
  </td>
</tr>
cs

-Script 단
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function myFunction(x) {
 
    var count = x.closest("tr").rowIndex;
 
    var fileValue = $("#icon"+count).closest("tr").find("input[type=hidden][value!='']").length;
 
    alert(fileValue);
 
    for(var b=1; b<fileValue+1; b++){
 
         var fileData = new Array();
 
         fileData[b] = document.getElementById("fileData"+ b).value;
 
    }
 
}
cs


대충보면 hidden name이 fileData인 값을 value값을 가져오고 싶어하는거같은데 몇가지 문제점을 보면


-Input ID의 하드코딩

-1부터 시작하는 아이디로 for문에서의 난잡함

-Array를 for문 안에서 생성함


이곳에서 file data의 값을 가져오고 싶다는거였는데 대충봐도 난잡하고 fileData가 1부터 시작해서 for문도 수정해야하고 대체적으로 수정이 필요해보였다


그래서 수정을 이렇게 해보았다


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
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
 
<script>
function myFunction(x) {
 
    var fileValue = $("input[name='fileData']").length;
    var fileData = new Array(fileValue);
    for(var i=0; i<fileValue; i++){                          
         fileData[i] = $("input[name='fileData']")[i].value;
    }
}
 
 
</script>
</head>
<body>
 
<tr>
  <td id="title">
      <input class="input" type="text" id="nameEdit4" name="nameEdit4" value="123">
      <input class="input" type="hidden" name="fileData" value="170620_검토중.xlsx">
      <input class="input" type="hidden" name="fileData" value="error.txt">
      <input class="input" type="hidden" name="fileData" value="1">
      <input class="input" type="hidden" name="fileData" value="2">
      <input class="input" type="hidden" name="fileData" value="3">
      <span class="value" value="">123</span>
  </td>
  <td>
    <div class="tools">
      <a class="modal detail-btn" href="#" data-modal-index="1"  >      
      <input type="button" value="클릭" onclick="myFunction()"/>
    </div>
  </td>
</tr>
 
</body>
</html>
cs


이런식으로 하면 유동적이게 fileData를 불러와서 배열순으로 값을 넣어서 보여줄수가있다

fileData 라는 name이 다른부분에도 있다면 그부분의 name을 다르게 주거나 유니크하게 셀렉트할수있도록 수정해야할것같다

반응형
반응형

출처:https://code.i-harness.com/ko/q/60f0


누구든지 jQuery의 문자열에서 HTML을 쉽게 벗어날 수있는 방법을 알고 있습니까? 

임의의 문자열을 전달하고 HTML 페이지 (JavaScript / HTML 삽입 공격 방지)에 표시되도록 적절하게 

이스케이프 처리해야합니다. 이 작업을 수행하기 위해 jQuery를 확장 할 수 있다고 확신하지만

이 작업을 수행하는 데 필요한 프레임 워크에 대해 충분히 알지 못합니다.

 Answers


jQuery를 사용하기 때문에 요소의 text 속성을 설정할 수 있습니다.

// before:
// <div class="someClass">text</div>
var someHtmlString = "<script>alert('hi!');</script>";

// set a DIV's text:
$("div.someClass").text(someHtmlString);
// after: 
// <div class="someClass">&lt;script&gt;alert('hi!');&lt;/script&gt;</div>

// get the text in a string:
var escaped = $("<div>").text(someHtmlString).html();
// value: 
// &lt;script&gt;alert('hi!');&lt;/script&gt;

mustache.js의 솔루션 도 있습니다 .

var entityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#39;',
  '/': '&#x2F;',
  '`': '&#x60;',
  '=': '&#x3D;'
};

function escapeHtml (string) {
  return String(string).replace(/[&<>"'`=\/]/g, function (s) {
    return entityMap[s];
  });
}

HTML로 탈출했다면 정말 필요한 것이라고 생각할 수있는 것은 세 가지뿐입니다.

html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");

사용 사례에 따라 " to &quot; 와 같은 작업을 수행해야 할 수도 있습니다. 목록이 충분히 크면 배열을 사용합니다.

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]
for(var item in findReplace)
    escaped = escaped.replace(findReplace[item][0], findReplace[item][1]);

encodeURIComponent() 는 URL이 아닌 HTML 만 이스케이프 처리합니다.

나는 이것을하는 작은 기능을 썼다. 그것은 " , & , < 그리고 > 만 이스케이프합니다. (대개 필요한 것은 모두 필요합니다.

 .replace() 모든 변환 작업을 수행하기 위해 .replace() 를 사용한다는 점에서 이전 제안 된 솔루션보다 약간 더 우아합니다. 

EDIT 2 : 코드 복잡성이 줄어들어 원래 코드에 대해 궁금한 점이 있다면 함수를 더 작고 깔끔하게 만듭니다.이 답변의 끝 부분을 참조하십시오.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&<>]/g, function (a) {
        return { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' }[a];
    });
}

이것은 일반 Javascript이며 jQuery는 사용되지 않습니다.

탈출구 ' 와 ' 도

mklement 의 코멘트에 대한 응답으로 편집하십시오.

위의 기능은 모든 문자를 포함하도록 쉽게 확장 될 수 있습니다. 이스케이프 할 문자를 더 지정하려면 

정규 표현식의 문자 클래스 (예 : /[...]/g )와 chr 객체의 항목으로 모두 삽입하기 만하면됩니다. 

EDIT 2 : 같은 방식으로이 기능을 짧게합니다.)

function escapeHtml(text) {
    'use strict';
    return text.replace(/[\"&'\/<>]/g, function (a) {
        return {
            '"': '&quot;', '&': '&amp;', "'": '&#39;',
            '/': '&#47;',  '<': '&lt;',  '>': '&gt;'
        }[a];
    });
}

위의 &#39; 아포스트로피 (상징적 인 엔티티가 대신 사용될 수도 있음 - XML로 정의되었지만 원래 HTML 스펙에 포함되지 않았기 때문에

 모든 브라우저에서 지원되지 않을 수도 있음 참조 : HTML 문자 인코딩에 관한 Wikipedia 기사 ). 

또한 십진법 엔티티를 사용하는 것이 16 진수를 사용하는 것보다 더 광범위하게 지원된다는 것을 기억하지만, 지금은 소스를 찾을 수없는 것 같습니다.

 (그리고 16 진법 엔티티를 지원하지 않는 많은 브라우저가있을 수 없습니다.)

참고 : 이스케이프 된 문자 목록에 / 와 ' 를 추가하는 것은 HTML에서 특별한 의미가 없으므로 유용하지 않습니다. 이스케이프 처리 할 필요 가 없습니다.

원래 escapeHtml 함수

편집 2 : 원래 함수는 변수 ( chr )를 사용하여 .replace() 콜백에 필요한 객체를 저장합니다. 

이 변수는 범위를 지정하기 위해 익명의 추가 함수가 필요하기 때문에 함수가 불필요하게 커지고 복잡해졌습니다.

var escapeHtml = (function () {
    'use strict';
    var chr = { '"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;' };
    return function (text) {
        return text.replace(/[\"&<>]/g, function (a) { return chr[a]; });
    };
}());

두 버전 중 어느 버전이 더 빠르는지는 테스트하지 않았습니다. 그럴 경우 여기에서 정보와 링크를 자유롭게 추가하십시오.

쉽게 밑줄을 사용할 수 있습니다.

_.escape(string) 

Underscore 는 네이티브 j가 제공하지 않는 많은 기능을 제공하는 유틸리티 라이브러리입니다. 

밑줄과 같은 API이지만 성능이 좋도록 다시 작성된 lodash 도 있습니다.

내가이 파티에 얼마나 늦었는지 알지만, jQuery를 필요로하지 않는 아주 쉬운 해결책이있다.

escaped = new Option(unescaped).innerHTML;

편집 :이 따옴표를 이스케이프하지 않습니다. 따옴표를 이스케이프해야하는 유일한 경우는

 내용이 HTML 문자열 내의 속성에 인라인으로 붙여 넣기 될 경우입니다. 

이 일을하는 것이 좋은 디자인이라고 상상하는 것이 어렵습니다.

편집 2 : 성능이 중요한 경우 최고 성능 솔루션 (약 50 %까지)은 여전히 ​​일련의 정규식 대체품입니다. 

최신 브라우저는 정규 표현식에 연산자가없고 문자열 만 포함하고 모두를 단일 작업으로 축소한다는 사실을 감지합니다.

깨끗하고 명확한 JavaScript 함수가 여기에 있습니다. 그것은 "몇 개의 <많은"과 같은 텍스트를 "소수의 <많은>"문자로 이스케이프합니다.

function escapeHtmlEntities (str) {
  if (typeof jQuery !== 'undefined') {
    // Create an empty div to use as a container,
    // then put the raw text in and get the HTML
    // equivalent out.
    return jQuery('<div/>').text(str).html();
  }

  // No jQuery, so use string replace.
  return str
    .replace(/&/g, '&amp;')
    .replace(/>/g, '&gt;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;');
}

Underscore.string lib를 사용해보십시오. jQuery와 함께 작동합니다.

_.str.escapeHTML('<div>Blah blah blah</div>')

산출:

'&lt;div&gt;Blah blah blah&lt;/div&gt;'

마지막 테스트 후 가장 빠르고 완벽하게 크로스 브라우저 호환 원시 자바 스크립트 (DOM) 솔루션을 추천 할 수 있습니다 :

function HTMLescape(html){
    return document.createElement('div')
        .appendChild(document.createTextNode(html))
        .parentNode
        .innerHTML
}

여러 번 반복하면 준비된 변수를 사용하여 수행 할 수 있습니다.

//prepare variables
var DOMtext = document.createTextNode("test");
var DOMnative = document.createElement("span");
DOMnative.appendChild(DOMtext);

//main work for each case
function HTMLescape(html){
  DOMtext.nodeValue = html;
  return DOMnative.innerHTML
}

내 최종 실적 비교 ( 스택 질문 )를보십시오.

나는 문자열 객체에 escapeHTML() 메소드를 추가하는 콧수염 escapeHTML() 예제를 개선했습니다.

var __entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
};

String.prototype.escapeHTML = function() {
    return String(this).replace(/[&<>"'\/]/g, function (s) {
        return __entityMap[s];
    });
}

그렇게하면 "Some <text>, more Text&Text".escapeHTML() 를 사용하는 것이 매우 쉽습니다. "Some <text>, more Text&Text".escapeHTML()

escape() 및 unescape() 는 HTML이 아닌 URL의 문자열을 인코딩 / 디코딩하기위한 것입니다.

사실, 나는 프레임 워크를 필요로하지 않는 트릭을하기 위해 다음 스 니펫을 사용한다.

var escapedHtml = html.replace(/&/g, '&amp;')
                      .replace(/>/g, '&gt;')
                      .replace(/</g, '&lt;')
                      .replace(/"/g, '&quot;')
                      .replace(/'/g, '&apos;');

underscore.js가 있으면 _.escape 사용 _.escape (위에 게시 된 jQuery 메서드보다 효율적입니다).

_.escape('Curly, Larry & Moe'); // returns: Curly, Larry &amp; Moe

위의 tghw의 예에서 오류가 발생했습니다.

<!-- WON'T WORK -  item[0] is an index, not an item -->

var escaped = html; 
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g,"&gt;"], [/"/g,
"&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(item[0], item[1]);   
}


<!-- WORKS - findReplace[item[]] correctly references contents -->

var escaped = html;
var findReplace = [[/&/g, "&amp;"], [/</g, "&lt;"], [/>/g, "&gt;"], [/"/g, "&quot;"]]

for(var item in findReplace) {
     escaped = escaped.replace(findReplace[item[0]], findReplace[item[1]]);
}

이것은 좋은 안전한 예입니다 ...

function escapeHtml(str) {
    if (typeof(str) == "string"){
        try{
            var newStr = "";
            var nextCode = 0;
            for (var i = 0;i < str.length;i++){
                nextCode = str.charCodeAt(i);
                if (nextCode > 0 && nextCode < 128){
                    newStr += "&#"+nextCode+";";
                }
                else{
                    newStr += "?";
                }
             }
             return newStr;
        }
        catch(err){
        }
    }
    else{
        return str;
    }
}
(function(undefined){
    var charsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };

    var replaceReg = new RegExp("[" + Object.keys(charsToReplace).join("") + "]", "g");
    var replaceFn = function(tag){ return charsToReplace[tag] || tag; };

    var replaceRegF = function(replaceMap) {
        return (new RegExp("[" + Object.keys(charsToReplace).concat(Object.keys(replaceMap)).join("") + "]", "gi"));
    };
    var replaceFnF = function(replaceMap) {
        return function(tag){ return replaceMap[tag] || charsToReplace[tag] || tag; };
    };

    String.prototype.htmlEscape = function(replaceMap) {
        if (replaceMap === undefined) return this.replace(replaceReg, replaceFn);
        return this.replace(replaceRegF(replaceMap), replaceFnF(replaceMap));
    };
})();

전역 변수, 일부 메모리 최적화가 없습니다. 용법:

"some<tag>and&symbol©".htmlEscape({'©': '&copy;'})

결과는 다음과 같습니다.

"some&lt;tag&gt;and&amp;symbol&copy;"

바닐라 js로 쉽게 할 수 있습니다.

단순히 텍스트 노드를 문서에 추가하십시오. 그것은 브라우저에 의해 이스케이프됩니다.

var escaped = document.createTextNode("<HTML TO/ESCAPE/>")
document.getElementById("[PARENT_NODE]").appendChild(escaped)
function htmlEscape(str) {
    var stringval="";
    $.each(str, function (i, element) {
        alert(element);
        stringval += element
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(' ', '-')
            .replace('?', '-')
            .replace(':', '-')
            .replace('|', '-')
            .replace('.', '-');
    });
    alert(stringval);
    return String(stringval);
}

NO JQUERY가 필요없는 2 가지 간단한 메소드 ...

다음과 같이 문자열의 모든 문자 를 인코딩 할 수 있습니다.

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

또는 & , 줄 바꿈, < , > , " 및 ' 대해 걱정할 주요 문자 를 대상으로 지정하십시오 .

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

var myString='Encode HTML entities!\n"Safe" escape <script></'+'script> & other tags!';

test.value=encode(myString);

testing.innerHTML=encode(myString);

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<p><b>What JavaScript Generated:</b></p>

<textarea id=test rows="3" cols="55"></textarea>

<p><b>What It Renders Too In HTML:</b></p>

<div id="testing">www.WHAK.com</div>

function htmlDecode(t){
   if (t) return $('<div />').html(t).text();
}

매력처럼 작동합니다.

이 답변 은 jQuery와 일반 JS 메소드를 제공하지만 DOM을 사용하지 않으면이 메소드가 가장 짧습니다.

unescape(escape("It's > 20% less complicated this way."))

이스케이프 된 문자열 : It%27s%20%3E%2020%25%20less%20complicated%20this%20way.

이스케이프 된 공간에서 문제가 발생하면 시도해보십시오.

unescape(escape("It's > 20% less complicated this way.").replace(/%20/g, " "))

이스케이프 처리 된 문자열 : It%27s %3E 20%25 less complicated this way.

유감스럽게도 JavaScript 버전 1.5 에서는 escape() 함수가 사용되지 않습니다 . 

encodeURI() 또는 encodeURIComponent() 는 대안이지만 무시하므로 ' , 마지막 코드 행은 다음과 같이 바뀝니다.

decodeURI(encodeURI("It's > 20% less complicated this way.").replace(/%20/g, " ").replace("'", '%27'))

모든 주요 브라우저는 여전히 짧은 코드를 지원하며 이전 웹 사이트의 수를 감안할 때 곧 변경 될 것입니다.

일반 자바 스크립트 이스케이프 예 :

function escapeHtml(text) {
    var div = document.createElement('div');
    div.innerText = text;
    return div.innerHTML;
}

escapeHtml("<script>alert('hi!');</script>")
// "&lt;script&gt;alert('hi!');&lt;/script&gt;"

이 정보를 데이터베이스 에 저장하는 경우 클라이언트 측 스크립트를 사용하여

HTML을 이스케이프 처리하는 것은 잘못된 것으로 서버 에서 수행해야 합니다 . 

그렇지 않으면 XSS 보호를 우회하기 쉽습니다.

내 요점을 분명히하기 위해 다음 답변 중 하나를 사용하는 예제가 있습니다.

말하자면 escapeHtml 함수를 사용하여 블로그의 주석에서 Html을 이스케이프 처리 한 다음 서버에 게시합니다.

var entityMap = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    '"': '&quot;',
    "'": '&#39;',
    "/": '&#x2F;'
  };

  function escapeHtml(string) {
    return String(string).replace(/[&<>"'\/]/g, function (s) {
      return entityMap[s];
    });
  }

사용자는 다음을 수행 할 수 있습니다.

  • POST 요청 매개 변수를 편집하고 주석을 javascript 코드로 바꿉니다.
  • 브라우저 콘솔을 사용하여 escapeHtml 함수를 덮어 씁니다.

사용자가이 스 니펫을 콘솔에 붙여 넣으면 XSS 유효성 검사를 건너 뜁니다.

function escapeHtml(string){
   return string
}

당신이 재 탈출을 방지하지 않으면 모든 솔루션은 쓸모가 없습니다. 예를 들어, 대부분의 솔루션은 이스케이프 & &amp; .

escapeHtml = function (s) {
    return s ? s.replace(
        /[&<>'"]/g,
        function (c, offset, str) {
            if (c === "&") {
                var substr = str.substring(offset, offset + 6);
                if (/&(amp|lt|gt|apos|quot);/.test(substr)) {
                    // already escaped, do not re-escape
                    return c;
                }
            }
            return "&" + {
                "&": "amp",
                "<": "lt",
                ">": "gt",
                "'": "apos",
                '"': "quot"
            }[c] + ";";
        }
    ) : "";
};


반응형
반응형

사실 SHA256이나 MD5 같은 단방향 암호화를 전송하는측에서 왜 해야 하는지 의문이 들기도 하지만,
모든 개발이 생각하는대로 흘러가지 않는만큼 여러가지(?) 이유로 전송하는 문자열을 암호화 해야 하는 이슈가 발생하였다.

암호화를 SHA-256으로 하기로 협업과 약속하고 자바스크립트로 SHA256 암호화 할 수 있는 방법으로 구글링 해 보니, 쉽게 찾을 수 있었다. 이미 외국의 개발자분이 자바스크립트로 구성된 함수를 제작하여 공개하셨다.

함수는 아래와 같으며, 원 출처지인 http://www.webtoolkit.info/javascript_sha256.html#.VuJRJuY4tFC 을 통해서도 확인이 가능하다.


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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<script type="text/javascript">
    /**
    *
    *  Secure Hash Algorithm (SHA256)
    *  http://www.webtoolkit.info/
    *
    *  Original code by Angel Marin, Paul Johnston.
    *
    **/
      
    function SHA256(s){
      
        var chrsz   = 8;
        var hexcase = 0;
      
        function safe_add (x, y) {
            var lsw = (x & 0xFFFF+ (y & 0xFFFF);
            var msw = (x >> 16+ (y >> 16+ (lsw >> 16);
            return (msw << 16| (lsw & 0xFFFF);
        }
      
        function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
        function R (X, n) { return ( X >>> n ); }
        function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
        function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
        function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
        function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
        function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
        function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
      
        function core_sha256 (m, l) {
             
            var K = new Array(0x428A2F980x713744910xB5C0FBCF0xE9B5DBA50x3956C25B0x59F111F1,
                0x923F82A40xAB1C5ED50xD807AA980x12835B010x243185BE0x550C7DC3,
                0x72BE5D740x80DEB1FE0x9BDC06A70xC19BF1740xE49B69C10xEFBE4786,
                0xFC19DC60x240CA1CC0x2DE92C6F0x4A7484AA0x5CB0A9DC0x76F988DA,
                0x983E51520xA831C66D0xB00327C80xBF597FC70xC6E00BF30xD5A79147,
                0x6CA63510x142929670x27B70A850x2E1B21380x4D2C6DFC0x53380D13,
                0x650A73540x766A0ABB0x81C2C92E0x92722C850xA2BFE8A10xA81A664B,
                0xC24B8B700xC76C51A30xD192E8190xD69906240xF40E35850x106AA070,
                0x19A4C1160x1E376C080x2748774C0x34B0BCB50x391C0CB30x4ED8AA4A,
                0x5B9CCA4F0x682E6FF30x748F82EE0x78A5636F0x84C878140x8CC70208,
                0x90BEFFFA0xA4506CEB0xBEF9A3F70xC67178F2);
 
            var HASH = new Array(0x6A09E6670xBB67AE850x3C6EF3720xA54FF53A0x510E527F
0x9B05688C0x1F83D9AB0x5BE0CD19);
 
            var W = new Array(64);
            var a, b, c, d, e, f, g, h, i, j;
            var T1, T2;
      
            m[l >> 5|= 0x80 << (24 - l % 32);
            m[((l + 64 >> 9<< 4+ 15= l;
      
            for ( var i = 0; i<m.length; i+=16 ) {
                a = HASH[0];
                b = HASH[1];
                c = HASH[2];
                d = HASH[3];
                e = HASH[4];
                f = HASH[5];
                g = HASH[6];
                h = HASH[7];
      
                for ( var j = 0; j<64; j++) {
                    if (j < 16) W[j] = m[j + i];
                    else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
      
                    T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
                    T2 = safe_add(Sigma0256(a), Maj(a, b, c));
      
                    h = g;
                    g = f;
                    f = e;
                    e = safe_add(d, T1);
                    d = c;
                    c = b;
                    b = a;
                    a = safe_add(T1, T2);
                }
      
                HASH[0= safe_add(a, HASH[0]);
                HASH[1= safe_add(b, HASH[1]);
                HASH[2= safe_add(c, HASH[2]);
                HASH[3= safe_add(d, HASH[3]);
                HASH[4= safe_add(e, HASH[4]);
                HASH[5= safe_add(f, HASH[5]);
                HASH[6= safe_add(g, HASH[6]);
                HASH[7= safe_add(h, HASH[7]);
            }
            return HASH;
        }
      
        function str2binb (str) {
            var bin = Array();
            var mask = (1 << chrsz) - 1;
            for(var i = 0; i < str.length * chrsz; i += chrsz) {
                bin[i>>5|= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
            }
            return bin;
        }
      
        function Utf8Encode(string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
      
            for (var n = 0; n < string.length; n++) {
      
                var c = string.charCodeAt(n);
      
                if (c < 128) {
                    utftext += String.fromCharCode(c);
                }
                else if((c > 127&& (c < 2048)) {
                    utftext += String.fromCharCode((c >> 6| 192);
                    utftext += String.fromCharCode((c & 63| 128);
                }
                else {
                    utftext += String.fromCharCode((c >> 12| 224);
                    utftext += String.fromCharCode(((c >> 6& 63| 128);
                    utftext += String.fromCharCode((c & 63| 128);
                }
      
            }
      
            return utftext;
        }
      
        function binb2hex (binarray) {
            var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
            var str = "";
            for(var i = 0; i < binarray.length * 4; i++) {
                str += hex_tab.charAt((binarray[i>>2>> ((3 - i%4)*8+4)) & 0xF+
                hex_tab.charAt((binarray[i>>2>> ((3 - i%4)*8  )) & 0xF);
            }
            return str;
        }
      
        s = Utf8Encode(s);
        return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
      
    }
     
     
     
     
 
 
    // 암호화 확인
    console.log(SHA256("Test")) ;
 
</script>
 
cs

출처: http://fruitdev.tistory.com/191 [과일가게 개발자]




레퍼런스 문서

http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf

각 block 내용 및 W[64]의 내용들이 자세하게 나와있음

http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA256.pdf

위와 비슷한 정보 

http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf



sha256은 hash 함수의 일종이다

hash 함수라는게 뭐냐면 다 알고 있겠지만 간단히 설명해보겠다


y = x + 2 이런 함수는 y를 알면 x도 알 수 있다

하지만 y = hash(x) 이런 해쉬 함수는 y를 알아도 x를 알 수 없는게 특징이다

그리고 모든 x값에 대해 각기 다른 y값을 내뱉는 특징 때문에 x가 원본임을 증명하는 일종의 시그니쳐로도 사용할 수 있다

(정확하게 말하자면 hash 함수는 단사함수가 아니다. hash collision이 있어서 다른 x임에도 같은 y값이 나오는 경우도 있다.

 hash collision을 피하기 위해선 계산을 더 복잡하게 하면 된다. 적당한 기회 비용을 두고 밀당을 해야한다는 소리)


hash 결과값은 32bit 8개를 병렬로 늘어놓은 값 

32bit x 8 = 256bit 그래서 이름이 sha256이다


원본 메세지의 각 문자(ascii 8bit)를 적당히 잘라 붙이고 쉬프트하고 and, or 등등 해서 512bit 단위의 블럭으로 만들고 이를 볶고 지져 hash를 계산한다

512bit 블럭으로 만들기 위해 크면 자르고(parsing) 모자라면 붙인다(padding)


아래의 공식에 맞춰 hash 계산에 필요한 블럭을 만든다

L + 1 + k = 448mod512


L(data length)는 hash를 만들고 싶은 원본 message의 bit길이 이므로 무조건 8의 배수이다

구현할 때 447bit 이런거 머리 빠지게 고민할 필요 없다


그리고 중요한 정보 - little endian을 기준으로 동작하도록 설계되어있다

x86, arm을 보통 사용하는 우리는 짜증나는 endian 전환을 해야 한다



실제 구현 관련 정리 - 블럭 제작 방법 및 hash 계산 방법

hash 계산 및 업데이트

간단하므로 생략, fips 문서에 나온데로 4개의 절차를 수행하면 된다(복잡해 보이는 시그마 같은거 다 문서에 잘 정의 되어있다)


메세지 길이 = len

case 1. len < 56(448bit)

마지막에 1bit를 추가하고 448bit까지 0으로 채움

그리고 마지막 64bit는 총 메세지 길이(lenx8)를 기록한다

hash 계산, 업데이트


case 2. 56 <= len < 64

마지막에 1bit를 추가하고 512bit까지 0으로 채워 block을 만든다

그리고 hash를 계산, 업데이트 한다

그리고 448bit까지 모두 0으로 채우고 마지막 64bit를 총 메세지 길이(lenx8)를 기록한다

그리고 hash 계산, 업데이트


case 3. len >= 64(512bit 이상)

512bit 씩 block으로 잘라 hash 계산, 업데이트 한다

마지막 남는 메세지는 길이에 따라 case1 혹은 case2와 동일하게 진행


last

계산한 32bit 8개의 값을 나열하면 sha256 완성



기타 유용한 참고 소스 코드

kernel 에 포함된 sha....코드.......이해하기 너무 어려움

openssl 의 crypto/sha에 있는 코드들 추천, 다만 최적화 되어있는 부분은 이해하기 힘듬

https://github.com/b-con/crypto-algorithms 매우 추천 깔끔하게 정리 되어있음

반응형
반응형

1. 비밀번호 정규식




특수문자 / 문자 / 숫자 포함 형태의 8~15자리 이내의 암호 정규식

var regex = /^.*(?=^.{8,15}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[!@#$%^&+=]).*$/;

 

숫자와 문자 포함 형태의 6~12자리 이내의 암호 정규식

var regex = /^[A-Za-z0-9]{6,12}$/;


-사용예제


1
2
3
4
5
6
7
var passRule = /^[A-Za-z0-9]{6,12}$/;//숫자와 문자 포함 형태의 6~12자리 이내의 암호 정규식
 
if(!passRule.test($("input[id='PASS']").val())) {
    //경고
 
    return flase;
}
cs


2. 이메일 정규식





var regExp = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;


- / / 안에 있는 내용은 정규표현식 검증에 사용되는 패턴이 이 안에 위치함
- / /i 정규표현식에 사용된 패턴이 대소문자를 구분하지 않도록 i를 사용함
- ^ 표시는 처음시작하는 부분부터 일치한다는 표시임
- [0-9a-zA-Z] 하나의 문자가 []안에 위치한 규칙을 따른다는 것으로 숫자와 알파벳 소문지 대문자인 경우를 뜻 함
- * 이 기호는 0또는 그 이상의 문자가 연속될 수 있음을 말함


-사용 예제


1
2
3
4
5
6
var emailRule = /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;//이메일 정규식
 
if(!emailRule.test($("input[id='EMAIL']").val())) {            
            //경고
            return false;
}
cs



3. 핸드폰번호 정규식

var regExp = /^\d{3}-\d{3,4}-\d{4}$/;


4. 일반 전화번호 정규식

var regExp = /^\d{2,3}-\d{3,4}-\d{4}$/;


출처 : 

http://yyman.tistory.com/entry/Javascript-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%A0%95%EA%B7%9C%EC%8B%9D

https://webisfree.com/2016-05-12/%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A3%BC%EC%86%8C-%EA%B2%80%EC%A6%9D-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D



반응형
반응형

Javascript SE6 공부 참고용으로 퍼왔습니다~


출처: http://itstory.tk/entry/JavaScript-ES6-문법-정리 [덕's IT Story]


ECMAScript 6

이 문서는 https://github.com/lukehoban/es6features 를 번역한 내용입니다. 번역 문서를 읽는 중, 오타나 어색한 문장이 있으면 이슈를 등록해주세요!

Introduction

ECMAScript 2015로도 알려져 있는 ECMAScript 6는 ECMAScript 표준의 가장 최신 버전입니다. ES6는 새로운 언어 기능이 포함된 주요 업데이트이며, 2009년도에 표준화된 ES5 이후로 언어 기능에 대한 첫 업데이트이기도 합니다. 현재 주요 JavaScript 엔진들에서 ES6 기능들을 구현 중에 있습니다.

ECMAScript 6 언어의 전체 스펙을 확인하시려면 ES6 Standard를 확인하세요.

ES6는 아래의 새로운 기능들을 포함하고 있습니다.

ECMAScript 6 에 추가된 기능

Arrows

Arrows(화살표) 함수는 => 문법을 사용하는 축약형 함수입니다. C#, Java 8, CoffeeScript의 해당 기능과 문법적으로 유사합니다. Arrows는 표현식의 결과 값을 반환하는 표현식 본문(expression bodies)뿐만 아니라 상태 블럭 본문(statement block bodies)도 지원합니다. 하지만 일반 함수의 자신을 호출하는 객체를 가리키는 dynamic this와 달리 arrows 함수는 코드의 상위 스코프(lexical scope)를 가리키는 lexical this를 가집니다.

var evens = [2, 4, 6, 8,];

// Expression bodies (표현식의 결과가 반환됨)
var odds = evens.map(v => v + 1);   // [3, 5, 7, 9]
var nums = evens.map((v, i) => v + i);  // [2, 5, 8, 11]
var pairs = evens.map(v => ({even: v, odd: v + 1})); // [{even: 2, odd: 3}, ...]

// Statement bodies (블럭 내부를 실행만 함, 반환을 위해선 return을 명시)
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

// Lexical this
// 출력결과 : Bob knows John, Brian
var bob = {
  _name: "Bob",
  _friends: ["John, Brian"],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
}

printFriends() 함수의 서브루틴은 다음과 문법상 동일하게 동작합니다.

this._friends.forEach(function (f) {
    console.log(this._name + " knows " + f));
}.bind(this));

화살표 함수의 더 자세한 설명은 MDN Arrow Functions를 참고하세요. printFriends() 함수의 선언 표기법이 궁금하시면 MDN Object Initializer를 참고하세요.

Classes

ES6 클래스는 포로토타입 기반 객체지향 패턴을 더 쉽게 사용할 수 있는 대체재입니다. 클래스 패턴 생성을 더 쉽고 단순하게 생성할 수 있어서 사용하기도 편하고 상호운용성도 증가됩니다.

class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);

    this.idMatrix = SkinnedMesh.defaultMatrix();
    this.bones = [];
    this.boneMatrices = [];
    //...
  }
  update(camera) {
    //...
    super.update();
  }
  get boneCount() {
    return this.bones.length;
  }
  set matrixType(matrixType) {
    this.idMatrix = SkinnedMesh[matrixType]();
  }
  static defaultMatrix() {
    return new THREE.Matrix4();
  }
}

더 자세한 설명은 MDN Classes를 참고하세요.

Enhanced Object Literals

ES6에서 객체 리터럴은 선언문에서 프로토타입 설정, foo: foo 선언을 위한 단축 표기법, 메서드 정의, super 클래스 호출 및 동적 속성명을 지원하도록 향상 되었습니다. 그에 따라 객체 리터럴 및 클래스 선언이 더 밀접되어져, 객체기반 설계가 더 편리해졌습니다.

var obj = {
    // __proto__
    __proto__: theProtoObj,

    // ‘handler: handler’의 단축 표기
    handler,

    // Methods
    toString() {
     // Super calls
     return "d " + super.toString();
    },

    // Computed (dynamic) property names
    [ 'prop_' + (() => 42)() ]: 42
};

더 자세한 설명은 MDN Grammar and types: Object literals를 참고하세요.

Template Strings

Template Strings(ES6 부터는 Template literals라 부름)는 문법적으로 더 편하게 string을 생성할 수 있게 합니다. 이는 Perl, Python 등의 문자열 보간(string interpolation)과 유사합니다. Tagged template literals는 인젝션 공격 방어 혹은 문자열로 부터 상위 데이터 구조체 재조립 등을 위해 string 생성을 커스터마이징이 가능하게끔 해줍니다.

// Basic literal string creation
`In JavaScript '\n' is a line-feed.`

// Multiline strings
`In JavaScript this is
 not legal.`

// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Construct an HTTP request prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     { "foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);

더 자세한 설명은 MDN Template literals를 참고하세요.

Destructuring

Destructuring는 배열과 객체에 패턴 매칭을 통한 데이터 바인딩을 제공합니다. Destructuring는 할당 실패에 유연하며, 실패 시 undefined 값이 자동할당 됩니다. 또한 foo["bar"]와 같이 객체의 속성 값도 자동으로 검색하여 바인딩해줍니다.

// list matching
var [a, , b] = [1,2,3];

// object matching
var { op: a, lhs: { op: b }, rhs: c }
       = getASTNode()

// object matching 단축 표기
// binds `op`, `lhs` and `rhs` in scope
var {op, lhs, rhs} = getASTNode()

// parameter에서도 사용 가능
function g({name: x}) {
  console.log(x);
}
g({name: 5})

// Fail-soft destructuring
var [a] = [];
a === undefined;

// Fail-soft destructuring with defaults
var [a = 1] = [];
a === 1;

더 자세한 설명은 MDN Destructuring assignment를 참고하세요.

Default + Rest + Spread

파라미터에 기본 값을 설정할 수 있습니다.

function f(x, y=12) {
  // y is 12 if not passed (or passed as undefined)
  return x + y;
}
f(3) // 15

가변인자를 사용가능하며, 배열로 치환시켜 줍니다. Rest parameters는 arguments 보다 직관성을 제공합니다.

function f(x, ...y) {
  // y is an Array ["hello", true]
  return x * y.length;
}
f(3, "hello", true) // 6

함수 호출 시 배열을 일련의 인자에 나누어 주입시켜 줍니다.

function f(x, y, z) {
  return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) // 6

더 자세한 설명은 Default parametersRest parametersSpread Operator를 참고하세요.

Let + Const

블록 유효 범위를 갖는 새로운 변수 선언 방법을 지원합니다. let은 var와 유사하게 동작합니다. const는 재할당 및 재선언이 불가능합니다.

function f() {
  {
    let x;
    {
      // okay, block scoped name
      const x = "sneaky";
      // error, const
      x = "foo";
    }
    // error, already declared in block
    let x = "inner";
  }
}

var의 유효 범위는 전체 외부 함수까지이지만 let은 변수를 선언한 블록과 그 내부 블록들에서 유효합니다.

function varTest() {
    var x = 31;
    if (true) {
        var x = 71;  // same variable!
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function letTest() {
    let x = 31;
    if (true) {
        let x = 71;  // different variable
        console.log(x);  // 71
    }
    console.log(x);  // 31
}
function varTest() {
    if (true) {
        var x = 71;
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function varTest() {
    let x = 71;
    if (true) {
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function varTest() {
    if (true) {
        let x = 71;
        console.log(x);  // 71
    }
    console.log(x);  // Uncaught ReferenceError: x is not defined
}

더 자세한 설명은 let statementconst statement를 참고하세요.

Iterators + For..Of

Iterator 객체는 CLR의 IEnumerable 혹은 Java의 Iterable처럼 사용자 정의의 반복을 가능하게 해줍니다. for..of 반복문이 ES6에서 추가 되었으며 for..in 반복문과 달리 iterator 기반의 컬렉션 전용 반복문입니다. for in 반복문과의 차이점은 for in vs for of를 참고하세요.

let fibonacci = {
    [Symbol.iterator]() {
        let pre = 0, cur = 1;

        return {
            next() {
                [pre, cur] = [cur, pre + cur];
                return { done: false, value: cur }
            }
        }
    }
}

for (var n of fibonacci) {
    // truncate the sequence at 1000
    if (n > 1000)
        break;
    console.log(n); // 1, 2, 3, 5, 8, ...987
}

Iteration은 아래의 duck-type 인터페이스를 기반으로 합니다. (설명을 위해 TypeScript의 타입 문법을 사용하였습니다)

interface IteratorResult {
    done: boolean;
    value: any;
}
interface Iterator {
    next(): IteratorResult;
}
interface Iterable {
    [Symbol.iterator](): Iterator
}

더 자세한 설명은 MDN for…of를 참고하세요.

Generators

Generators는 function*와 yield 키워드를 이용하여 iterator 선언을 단순하게 작성할 수 있게 도와줍니다. function*로 선언한 함수는 Generator 객체를 반환합니다. Generators는 iterator의 하위 타입이며 next와 throw 메서드를 가지고 있습니다. 이 메서드들로 인해 yield 키워드로 반환된 값은 다시 generator에 주입거나 예외처리를 할 수 있게 되었습니다.

참고: 해당 키워드는 비동기 프로그래밍의 ‘await’ 같은 기능이 가능하게끔 기반이 되었습니다. ES7의 await 제안서를 참고하세요.

var fibonacci = {
    [Symbol.iterator]: function*() {
        var pre = 0, cur = 1;
        for (;;) {
            [pre, cur] = [cur, pre + cur];
            yield cur;
        }
    }
}

for (var n of fibonacci) {
    // truncate the sequence at 20
    if (n > 20)
        break;
    console.log(n); // 1, 2, 3, 5, 8, 13
}
function* gen(){
  yield* ["a", "b", "c"];
}

var a = gen();

a.next(); // { value: "a", done: false }
a.next(); // { value: "b", done: false }
a.next(); // { value: "c", done: false }
a.next(); // { value: undefined, done: true }

generator 인터페이스는 다음과 같습니다. (설명을 위해 TypeScript의 타입 문법을 사용하였습니다)

interface Generator extends Iterator {
    next(value?: any): IteratorResult;
    throw(exception: any);
}

더 자세한 설명은 MDN Iteration protocols를 참고하세요.

Unicode

완전한 유니코드를 지원하기 위해 문자열에 새로운 유니코드 리터럴과 정규표현식에 u 모드가 추가되었습니다. 또한 21비트 형식까지 처리하기 위한 신규 API가 추가되었습니다. 이 추가된 기능은 JavaScript로 글로벌 앱을 만들 수 있도록 지원합니다.

// same as ES5.1
"𠮷".length == 2

// new RegExp behaviour, opt-in ‘u’
"𠮷".match(/./u)[0].length == 2

// new form
"\u{20BB7}" == "𠮷"  == "\uD842\uDFB7"

// new String ops
"𠮷".codePointAt(0) == 0x20BB7

// for-of iterates code points
for(var c of "𠮷") {
    console.log(c); // 𠮷
}

더 자세한 설명은 MDN RegExp.prototype.unicode를 참고하세요.

Modules

언어 차원에서 컴포넌트 정의를 위한 모듈을 지원합니다. 유명한 JavaScript 모듈 로더들(AMD, CommonJS)의 패턴을 적용시켰습니다. 런타임 동작은 호스트에 정의된 기본 로더에 의해 정의됩니다. 묵시적 비동기 형태로 요구되는 모듈들이 정상적으로 로드되기 전까지 코드가 실행되지 않습니다.

// lib/math.js
export function sum(x, y) {
    return x + y;
}
export var pi = 3.141593;
// app.js
import * as math from "lib/math";
console.log("2π = " + math.sum(math.pi, math.pi)); // 2π = 6.283186
// otherApp.js
import {sum, pi} from "lib/math";
console.log("2π = " + sum(pi, pi)); // 2π = 6.283186

export default와 export * 문법도 제공합니다.

// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
    return Math.log(x);
}
// app.js
import ln, {pi, e} from "lib/mathplusplus";
console.log("2π = " + ln(e)*pi*2);

더 자세한 내용은 import statementexport statement를 참고하세요.

Module Loaders

Module Loaders는 다음을 지원합니다.

  • 동적 로딍(Dynamic loading)
  • 상태 격리(State isolation)
  • 전역 네임스페이스 격리(Global namespace isolation)
  • 컴파일 훅(Compilation hooks)
  • 중첩 가상화(Nested virtualization)

기본으로 사용할 모듈 로더를 설정할 수 있으며, 로더를 새로 생성하여 격리되거나 제한된 맥락에서 코드를 로드할 수 있습니다.

// 동적 로딩 – ‘System’ is default loader
System.import('lib/math').then(function(m) {
    console.log("2π = " + m.sum(m.pi, m.pi));
});

// 실행 샌드박스 생성 – new Loaders
var loader = new Loader({
    global: fixup(window) // replace ‘console.log’
});
loader.eval("console.log('hello world!');");

// 모듈 캐시 직접 조작
System.get('jquery');
System.set('jquery', Module({$: $})); // WARNING: not yet finalized

Map + Set + WeakMap + WeakSet

일반 알고리즘을 위한 효율적인 데이터 구조를 제공합니다. WeakMap과 WeakSet는 메모리 누수로 부터 자유롭게 해줍니다. 이들 내 저장된 객체에 다른 참조가 없는 경우, garbage collection 될 수 있습니다.

// Sets
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;

// Maps
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;

// Weak Maps
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size // undefined (사용된 곳이 없기 때문)

// Weak Sets
var ws = new WeakSet();
ws.add({ data: 42 });
wm.size // undefined (사용된 곳이 없기 때문)

더 자세한 내용은 MDN MapSetWeakMapWeakSet를 참고하세요.

Proxies

프록시(Proxy)를 사용하면 호스트 객체에 다양한 기능을 추가하여 객체를 생성할 수 있습니다. interception, 객체 추상화, 로깅/수집, 값 검증 등에 사용될 수 있습니다.

// Proxying a normal object
var target = {};
var handler = {
  get: function (receiver, name) {
    return `Hello, ${name}!`;
  }
};

var p = new Proxy(target, handler);
p.world // 'Hello, world!';
// Proxying a function object
var target = function () { return 'I am the target'; };
var handler = {
  apply: function (receiver, ...args) {
    return 'I am the proxy';
  }
};

var p = new Proxy(target, handler);
p() // 'I am the proxy';
let validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError('The age is not an integer');
            }
            if (value > 200) {
                throw new RangeError('The age seems invalid');
            }
        }

        // The default behavior to store the value 
        obj[prop] = value;
    }
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = 'young'; // Throws an exception
person.age = 300; // Throws an exception

proxy의 handler가 가질 수 있는 트랩(trap)들입니다.

var handler =
{
  get:...,
  set:...,
  has:...,
  deleteProperty:...,
  apply:...,
  construct:...,
  getOwnPropertyDescriptor:...,
  defineProperty:...,
  getPrototypeOf:...,
  setPrototypeOf:...,
  enumerate:...,
  ownKeys:...,
  preventExtensions:...,
  isExtensible:...
}

더 자세한 내용은 MDN Proxy를 참고하세요.

Symbols

심볼(Symbol)은 객체 상태의 접근 제어를 가능하게 합니다. Symbol은 새로운 원시 타입으로 이름 충돌의 위험 없이 속성(property)의 키(key)로 사용할 수 있습니다. 옵션 파라미터인 description는 디버깅 용도로 사용되며 식별 용도는 아닙니다. Symbol은 고유(unique)하며, Object.getOwnPropertySymbols와 같은 reflection 기능들로 접근할 수 있기 때문에 private 하진 않습니다(for in나 Object.keys()로는 접근 불가).

var map = {};
var a = Symbol('a');

map[a] = 123;
map["b"] = 456;

console.log(map[a]); // 123
console.log(map["b"]); // 456

for (let key in map) {
    console.log(key); // b
}

Object.keys(map); // ["b"]

더 자세한 내용은 ES6 In Depth: 심볼 (Symbol)를 참고하세요.

Subclassable Built-ins

ES6에서 ArrayDate, DOM Element 같이 내장 객체들은 상속이 가능합니다. 객체 생성 시 호출되는 Ctor 함수는 다음의 2단계를 가집니다.(둘다 가상적으로 실행)

  • 객체 할당을 위해 Ctor[@@create] 호출하여
  • 새로운 인스턴스의 생성자를 호출해 초기화 진행

아시다싶이 @@create 심볼은 Symbol.create를 통해 만들어졌습니다.

// Pseudo-code of Array
class Array {
    constructor(...args) { /* ... */ }
    static [Symbol.create]() {
        // Install special [[DefineOwnProperty]]
        // to magically update 'length'
    }
}

// User code of Array subclass
class MyArray extends Array {
    constructor(...args) { super(...args); }
}

// Two-phase 'new':
// 1) Call @@create to allocate object
// 2) Invoke constructor on new instance
var arr = new MyArray();
arr[1] = 12;
arr.length == 2

Math + Number + String + Array + Object APIs

core Math 라이브러리, Array 생성 helper, String helper, 복사를 위한 Object.assign 등 많은 라이브러리들이 추가되었습니다.

Number.EPSILON
Number.isInteger(Infinity) // false
Number.isNaN("NaN") // false

Math.acosh(3) // 1.762747174039086
Math.hypot(3, 4) // 5
Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2

"abcde".includes("cd") // true
"abc".repeat(3) // "abcabcabc"

Array.from(document.querySelectorAll('*')) // Returns a real Array
Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior
[0, 0, 0].fill(7, 1) // [0,7,7]
[1, 2, 3].find(x => x == 3) // 3
[1, 2, 3].findIndex(x => x == 2) // 1
[1, 2, 3, 4, 5].copyWithin(3, 0) // [1, 2, 3, 1, 2]
["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"]
["a", "b", "c"].keys() // iterator 0, 1, 2
["a", "b", "c"].values() // iterator "a", "b", "c"

Object.assign(Point, { origin: new Point(0,0) })

더 자세한 내용은 NumberMathArray.fromArray.ofArray.prototype.copyWithinObject.assign를 참고하세요.

Binary and Octal

2진법 (b), 8진법 (o) numeric 리터럴 형식이 추가되었습니다.

0b111110111 === 503 // true
0o767 === 503 // true

Promises

Promise는 비동기 프로그래밍을 위한 라이브러리입니다. Promise는 미래에 생성되는 값을 나타내는 일급 객체입니다. Promise는 현존하는 많은 JavaScript 라이브러리에 사용되고 있습니다.

function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration);
    })
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("hmm");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
})

더 자세한 내용은 MDN Promise를 참고하세요.

Reflect API

Reflection API는 런타임 시 객체에 대해 작업을 수행할 수 있습니다. 프록시 트랩(proxy traps)와 같은 메타 함수들을 가지고 있습니다. Reflection은 프록시를 구현하는데 유용합니다.

class Greeting {
    constructor(name) {
        this.name = name;
    }

    greet() {
      return `Hello ${name}`;
    }
}

function greetingFactory(name) {
    return Reflect.construct(Greeting, [name], Greeting);
}

greetingFactory('a'); // Greeting {name: "a"}

더 자세한 내용은 MDN Reflect를 참고하세요.

Tail Calls

마지막에 호출되는 함수가 호출 스택이 초과되게 하지 않습니다. 재귀 알고리즘을 매우 큰 입력 값에서도 안전하게 만듭니다.

function factorial(n, acc = 1) {
    'use strict';
    if (n <= 1) return acc;
    return factorial(n - 1, n * acc);
}

// 현재 대부분의 자바스크립트 엔진에서 스택 오버플로우가 일어나지만,
// ES6에서는 입력 값이 커도 안전하다
factorial(100000);



이외에


개발 문서 링크 참조해서 나중에 봐야겠습니다


http://es6-features.org/#Constants




반응형
반응형

웹페이지에서 선택박스 일명 셀렉트박스(SelectBox) 를 클릭할때마다 검색조건이 바뀌거나


페이지가 바뀌거나 하는걸 보셨을겁니다


기본적인 것이지만 경험해본적이 없으면 어떤방식으로 하는지 알기힘든부분입니다


간단하게 예제 몇가지를 통하여 알아보겠습니다


1. Question


선택을 할 수 있도록 셀렉트 박스를 만들었습니다.

샐랙트 박스에서 년도를 선택하면 바로 화면이 년도에 맞춰서 바로바로 바꿔주고 싶습니다. 

function으로 하는거 같은 어찌해야 할가요?


1
2
3
4
5
<select name="searchYear" id="searchYear">
<option value="2017">2017</option>
<option value="2018">2018</option>
<option value="2019">2019</option>
</select>
cs


2. Example1


1
2
3
4
5
<select name="searchYear" id="searchYear" onchange="펑션명()">
<option value="2017">2017</option>
<option value="2018">2018</option>
<option value="2019">2019</option>
</select>
cs



3. Example2


1
2
3
$("#searchYear").change(function(){
    var yearVal =  $(this).val();
})
cs

w

두가지 방법이 있는데

예제1 처럼 onchange 이벤트에 함수를 걸어주거나

change 이벤트를 태우는 방법이있습니다

방법은 여러가지이지만 개발시에는 둘중 한가지만으로 통일해서 개발하는것이 가독성에 좋습니다

적용해보시길 바랍니다






[javascript] selectbox 선택에 따라 두번째 selectbox 값 변화


selectbox의 선택에 따라 두번째 selectbox의 값이 변해야하는 경우가 있습니다.

지역 선택을 해야할 때나 품목 선택을 해야할 때가 그런 경우죠.

이때 사용하게 되는 것이, 해당하는 객체 값이 변할 때 발생하는 이벤트 함수인 onchange라는 함수입니다.

예제를 먼저 살펴볼까요. 먼저  html 부분에 해당 예제소스를 넣어주세요. 



1
2
3
4
5
6
7
8
9
10
<select onchange="categoryChange(this)">
  <option>걸그룹을 선택해주세요</option>
  <option value="a">블랙핑크</option>
  <option value="b">에프엑스</option>
  <option value="c">EXID</option>
</select>
 
<select id="good">
<option>좋아하는 멤버를 선택해주세요</option>
</select>


지극히 개인취향적인 걸그룹이 담긴 selectbox에 내용을 담고 다음에 javascript 스크립트를 넣어주면 완성입니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function categoryChange(e) {
  var good_a = ["지수", "제니", "로제", "리사"];
  var good_b = ["빅토리아", "엠버", "루나", "크리스탈"];
  var good_c = ["LE", "하니", "정화", "혜린", "솔지"];
  var target = document.getElementById("good");
 
  if(e.value == "a") var d = good_a;
  else if(e.value == "b") var d = good_b;
  else if(e.value == "c") var d = good_c;
 
  target.options.length = 0;
 
  for (x in d) {
    var opt = document.createElement("option");
    opt.value = d[x];
    opt.innerHTML = d[x];
    target.appendChild(opt);
  }
}





단지 value값만을 가져온다면 단순히 document.getElementByName("selBox").value   <---이렇게만 해줘도 된다.
그렇지만 "한국","미국","중국"처럼 내용값을 가져오려면

ex) 
<select name="selBox">
  <option value="1">한국</option>    <--0번째값
  <option value="2">미국</option>    <--1번째값  
  <option value="3">중국</option>    <--2번째값

</select>


document.getElementByName("selBox")[document.getElementByName("selBox").selelctedIndex].text
*만약2번을 선택한경우 selBox[1]번째의 text값을 가져오는것이다.



출처: http://sepiroth11.tistory.com/entry/자바스크립트select박스의-valuetext값을-얻어오기 [세피로스's 이야기]




반응형

'IT > Javascript|Jquery' 카테고리의 다른 글

비밀번호 /이메일/전화번호/핸드폰 정규식  (5) 2018.01.09
[JavaScript] ES6 문법 정리  (0) 2018.01.08
ajax 로딩시 새로고침 문제  (6) 2018.01.03
promise 패턴 예제  (0) 2018.01.02
ajax 배열전송  (0) 2018.01.02
반응형

가끔은 실무 개발중에 일어날수있는 문제들도 다뤄보고자 한다

form 태그를 사용하면서 ajax 도 태울시에 페이지가 새로고침 하는문제가 종종발생한다


1
2
3
4
5
6
7
8
9
10
11
12
13
var paramJson = {id : $("#_id").val(), pw : $("#_pw").val()};
 
$.ajax({
    type : 'POST'// Http Request Method로 POST로 지정
    url : "login.do"// 서버 요청 주소
    contentType : 'application/json;charset=UTF-8'// 서버 요청시 전송할 데이터가 UTF-8 형식의 JSON 객체임을 명시
    data : JSON.stringify(paramJson), // JavaScript 객체를 JSON 객체로 변환하여 서버 요청시 전송
    dataType : 'json'// 서버로부터 응답받을 데이터가 JSON 객체임을 명시하여 수작업 없이 응답 데이터를 JavaScript 객체로 획득
    success : function(res){alert(res.result);}, //callBackFunc(response)
    error : function(request, status, error){
        alert(error);
    }
});    
cs



이런식으로 ajax를 태우는데 

form 태그 내부의 버튼을 눌러서 발생되는 이벤트면 form 태그의 action을 타게되는것이다

해결방법은 이러하다


-방법1


1
2
3
4
5
6
7
8
9
10
<form name="data_form" method="post" action="./">
 
<!-- 클릭시 form(data_form)의 submit 동작을 하게 됨 -->
<button id="btn_example1">버튼 예제1</button>
 
<!-- 클릭시 submit 동작하지 않고 아무 반응 없음 -->
<button type="button" id="btn_example2">버튼 예제2</button>
 
</form>
<!--출처 : http://blog.freezner.com/archives/807 -->
cs


버튼에 type="button" 을 주면 action을 타지않게된다 



-방법2


1
2
3
4
5
6
7
8
9
10
11
12
$('#form_submit').click(function(){
   $.ajax({
        type: 'post',
        url: 'process.php',
        success: function(data){
            alert(data);
        }
   });
    return false//<- 이 문장으로 새로고침(reload)이 방지됨
});
 
//출처: http://somoly.tistory.com/103 [somoly.tistory.com]
cs

버튼이벤트에서 새로고침을 막는 방법도있다
방법은 여러가지지만 사용시에는 한가지로 통일시켜야 가독성이 좋고 어떤방식인지 헷갈리지않으니
주의하도록 한다


반응형

'IT > Javascript|Jquery' 카테고리의 다른 글

[JavaScript] ES6 문법 정리  (0) 2018.01.08
javascript 셀렉트박스(SelectBox) 바로실행  (2) 2018.01.04
promise 패턴 예제  (0) 2018.01.02
ajax 배열전송  (0) 2018.01.02
모바일/PC 코딩하기  (0) 2018.01.02
반응형
123

+ Recent posts