'Language/JAVASCRIPT'에 해당되는 글 106건

  1. 2016.12.23 프로토타입의 이해 01
  2. 2016.12.23 참고 강좌
  3. 2016.12.15 pply(), call() 메서드
  4. 2016.12.15 arguments 객체
  5. 2014.12.12 구글맵(차트)
  6. 2013.11.13 prototypejs
  7. 2013.05.22 마우스 커서 포지션 이동
  8. 2013.04.29 XMLHttpRequest 고급 기능 1
  9. 2013.04.29 XMLHttpRequest Level 2
  10. 2013.04.29 XMLHttpRequest

프로토타입의 이해 01

Language/JAVASCRIPT 2016. 12. 23. 10:40


* 이번에는 자바스크립트에서 객체지향을 기본적으로 구현하기 위한 개념인 prototype에 대하여 공부해보도록 하자. 이 개념은 단순한 자바스크립트 처리에서는 중요하지 않고 모르고 넘어간 경우가 많이 있었을테지만, 조금 복잡한 자바스크립트 또는 자바스크립트 라이브러리를 만드는데 있어서 객체 지향적인 개념을 활용하고자할 때 유용하게 사용할 수 있어서 알아두면 좋은 개념이다. 특히, 자바스크립트가 내부적으로 어떻게 동작하는지에 대하여 조금 더 이해를 하기 위하여 반드시 알아두고 넘어가자. 이번에는 약간 하단에서 돌아가는 방식에 대하여 알아볼 것이고 다음 글에서는 실제로 활용하는 방법과 상속에 대하여 알아볼 것인데, 이번 글에서 아주 깊숙한 내용까지 다룰 것이기 때문에 지금은 겉으로만 객체를 생성했을 때 일어나는 일들과 prototype을 알았더라도 읽고나면 그 내부까지 거의다 이해할 수 있으리라고 생각한다.



- 이전 글

2012/12/10 - [속깊은 자바스크립트 강좌] 시작 (예고편)

2012/12/17 - [속깊은 자바스크립트 강좌] 자바스크립트의 Scope와 Closure 기초

2013/01/07 - [속깊은 자바스크립트 강좌] function declaration vs function expression 차이점

2013/01/10 - [속깊은 자바스크립트 강좌] 함수를 호출하는 방법과 this의 이해

2013/01/21 - [속깊은 자바스크립트 강좌] Closure의 이해 / 오버로딩 구현하기

2013/01/30 - [속깊은 자바스크립트 강좌] Closure 쉽게 이해하기/실용 예제 소스

2013/02/13 - [속깊은 자바스크립트 강좌] 쉬어가기: 웹 개발 방법론의 변화/자바스크립트의 재발견



* prototype?

: 자바스크립트를 깊이있게 다루지 못했을 때에 처음으로 prototype이라는 말을 접하면 이것이 뭔가 하는 생각이 들기도 하고, 용도가 무엇이고 어떻게 써야할지 몰라서 방황할지도 모르고 심지어 prototype을 대충 접해보고는 처음부터 없었던 것처럼 다시 원래의 개발하던 방법으로 돌아갈지도 모른다. 사실 간단한 기능을 위하여 사용하는 자바스크립트에서는 prototype 개념을 알 필요가 별로 없지만, 객체지향을 선호하는 개발자들이라면, 또는 라이브러리를 통해 다양한 인스턴스들을 생성하고자하는 라이브러리 개발자라면, 그리고 자바스크립트를 조금 더 이해하고자 한다면 반드시 알아야할 개념이다. 일단 prototype의 사전적 의미를 보면, '원형'이라는 뜻을 가지고 있는데, 이 말 그대로 받아들이면 된다. 하지만 무엇의 원형인지를 생각하면서부터 다소 갸우뚱하게 된다. 따라서 먼저 객체에 대하여 알아보고 넘어가야할 것이다.



* 객체(object) 선언하고 생성하기

: 많은 웹 개발자들은 자바스크립트에서 객체를 선언하고 생성할 수 있다는 점을 모르고 있기도 하지만, 처음부터 자바의 기능들을 조금 가져오려고 했었기 때문에 그러한 기능들이 일부 포함되고 있고, 그 중 객체를 생성하는 부분 또한 포함되어있다. 하지만 핵심적인 다른 점이 있다면, 자바스크립트는 함수를 기반으로한 언어이기 때문에 객체의 선언은 함수를 통해서 하게 되는 것이다.


function Person(name, blog) {
    this.name = name;
    this.blog = blog;
}
var unikys = new Person("unikys", "unikys.tistory.com");
alert(unikys.name); // === "unikys"


- 덧: 자바스크립트에서는 개발자들 사이에서 명명 규칙으로 정하기를 함수의 첫 글자를 대문자로 (위에서는 Person의 P 대문자) 설정하게 되면, 해당하는 함수는 객체를 선언한 것임을 명시하는 전통적인 암묵적인 약속이 있다. 따라서, 객체를 선언하는 함수라면 첫글자는 대문자로 하고 만약 일반 함수라면 첫글자는 소문자로 하는 것을 습관화 들이면 좋을 것이다.


: 위의 내용은 그렇게 어려운 내용은 아니다. 그냥 기분상 class를 function으로 설정한듯한 기분이 드니까 그럴 것인데, 자바스크립트에서 new를 사용하게 되면 다른 과정들을 한번 깊게 살펴보자.



* new 연산자

:  자바나 C++에서 많이 쓰이는 new는 메모리를 새롭게 할당해서 해당하는 클래스의 생성자를 호출하면서 인스턴스를 초기화하고, 그 인스턴스를 생성하여 리턴하는 과정이 일어나게 되는데, 자바스크립트에서는 상당히 비슷하지만 조금은 다르게 받아들여야할 것이다. 왜냐하면 C++이나 자바에서는 new 뒤에 바로 class를 사용하지만 자바스크립트에서는 new 뒤에 바로 함수를 파라미터로 활용하기 때문이다. 함수를 바로 사용하기 때문에 이 함수는 생성하는 객체의 constructor(생성자)가 되는 것이고, 초기화도 바로 이 함수를 통해서 일어나게 되는데, 위의 함수에서도 사용했지만, 이전의 강좌 중에서 다뤘던 내용 중 "this"가 결정되는 방법에 대하여 다룬 적이 있다. 사실 다른 언어처럼 class로 되어있다면 그렇게 고민을 할 필요도 없겠지만, 자바스크립트는 function을 똑같이 객체의 생성자로서 활용하기 때문에 이전에 배웠던 this가 결정되는 방법과 위의 함수에서 this를 이용하는 것만 보면 얼핏 글로벌 변수(window)에다가 추가하는 듯한 기분이 들기도 하지만 뭔가는 다를 것 같은 기분이 들 것이다. 이럴 때에는 조금 더 깊이 있게 내부적으로 어떠한 단계들이 일어나는지 살펴보면 좋다. ECMAScript 5.1의 스펙을 살펴보자.


http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.2


: 위의 링크에 들어가면 객체가 생성될 때 일어나는 단계들을 설명하고 있다. 그 단계는 바로 아래와 같다.


When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:

1. Let obj be a newly created native ECMAScript object.

2. Set all the internal methods of obj as specified in 8.12.

3. Set the [[Class]] internal property of obj to "Object".

4. Set the [[Extensible]] internal property of obj to true.

5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".

6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.

7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.

8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.

9. If Type(result) is Object then return result.

10. Return obj.


: 위의 단계들을 순서대로 보면서 파악해도 되지만, 제일 중요한 부분을 살펴보면 바로 8번이다. 여기서 명시되어있기로는, obj는 this 값으로 설정한다고 되어있고, 이 obj는 1번에서 기본 object를 생성하는 것이라고 되어있다. 그리고 2번~7번까지는 이 obj에 다양한 속성들을 꾸며주는 것을 볼 수 있고 마지막 10번에는 이렇게 생성되고 꾸며진 obj를 리턴하여 new 연산자의 결과 값으로 설정되는 것을 알 수 있다. 따라서 생성자 내부에서는 this는 새로 생성된 obj로 설정되며, 이 this에는 위의 예처럼 this.name등 여러 가지 속성들을 추가하게 되면 생성되는 객체에 이러한 속성들이 추가되서 리턴하게 되는 것이다. 



* 그럼 prototype은 어디에 붙어있나?

: 위의 객체가 생성되는 단계 중에서 5번과 6번 단계를 살펴보면 "prototype"이라 속성이 나온다. 여기서 5단계를 해석해보면 F의 prototype 속성을 GET해서 설정한다고 나와있는데, 여기서 말하는 F라 하면 1단계 위의 설명에서 "a Function object F"가 생성자로 호출될 때라는 말이 있다. 따라서 이 prototype은 '생성자 함수 F'의 속성으로 설정된다는 것을 알 수 있다. 그럼 이제는 사전적의미의 prototype이 아닌 ECMAScript에서 정의하고 있는 prototype을 살펴보자. 아래의 링크는 constructor로 이어졌지만 그 바로 아래에 prototype이 써있다.


http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.4


prototype: object that provides shared properties for other objects

NOTE- When a constructor creates an object, that object implicitly references the constructor’s “prototype” property for the purpose of resolving property references. The constructor’s “prototype” property can be referenced by the program expression constructor.prototype, and properties added to an object’s prototype are shared, through inheritance, by all objects sharing the prototype. Alternatively, a new object may be created with an explicitly specified prototype by using the Object.create built-in function.


: ECMAScript에서 정의하고 있는 prototype이란 다른 객체들과 공유된 속성을 제공하는 객체라고 써있다. prototype이 하나의 객체라는 점을 주목하고 넘어가자. Note의 내용은 잠시 뒤에 다시 돌아와서 살펴보고, 일단 이제 prototype이 어디에 붙어있는지 알았으므로 실제로 활용하는 예를 '드디어' 한번 살펴보자. (prototype까지 오기가 너무 오래걸린것 같다 ㅠ)



* prototype 예

: 서론이 참 길었던 prototype 이론적인 이야기는 이제 마치고 실제로 예를 살펴보자. 위의 예에서 이어서 한번 만들어보자. 위에서 생성자 함수 F의 속성 prototype을 가져와서 새로운 객체에 추가한다고 되어있으므로, 위의 예에서 쓴 Person 함수에 prototype의 속성을 새로운 객체로 설정해보자.


function Person(name, blog) {
    this.name = name;
    this.blog = blog;
}
Person.prototype = {
    getName: function () {
        return this.name;
    },
    getBlog: function () {
        return this.blog;
    }
};
var unikys = new Person("unikys", "unikys.tistory.com");
var stranger = new Person("stranger", "www.google.com");
alert(unikys.getName()); // === "unikys"
alert(unikys.getBlog()); // === "unikys.tistory.com"
alert(stranger.getName()); // === "stranger"
alert(stranger.getBlog()); // === "www.google.com"

: 위와 같이 새로운 객체의 속성들을 함수로 넣어주고 이것을 Person.prototype으로 설정하니 새롭게 생성된 Person의 각 객체들 unikys와 stranger에서는 이 함수를 사용할 수 있게 되었다. 위의 ECMAScript의 정의에서 공유할 수 있는 속성들을 가지고 있다는 것이 바로 이 뜻이다. 즉, C++이나 자바에서 흔히 사용하는 클래스의 함수 선언과 같이 생각하면 쉬울 것이지만, 이 prototype 또한 하나의 객체로 이루어져서 유연하다는 것이 조금 다른 점이다. 예를 들면, 위의 소스에 이어서 아래와 같이 더 덧붙일수도 있다.


Person.prototype.introduce = function () {
    alert("Hi!, my name is " + this.name + ", please visit my blog " + this.blog);
};
unikys.introduce();  // === Hi!, my name is unikys, please visit my blog unikys.tistory.com


: 나중에 prototype에 특정 속성을 추가하게 되면 나머지 다른 객체들에도 전부다 똑같이 공유되는 속성으로 추가되는 것이다. 참으로 유연하고 놀랍다. 비슷하게, 모든 객체들이 공유하는 변수 또한 추가할 수 있다. 그냥 함수 대신 변수를 넣어주면 공유하는 변수가 되는 것이다.


Person.prototype.gender = "male";
alert(unikys.gender); // === "male"
alert(stranger.gender); // === "male"


: 하지만 여기서 궁금증이 약간 생길 것이다. 만약 stranger의 gender를 바꾼다면 나머지 unikys에서의 gender도 바뀌는, static 처럼 동작하게 될까?


Person.prototype.gender = "male";
alert(stranger.gender); // === "male";
stranger.gender = "female";

alert(unikys.gender); // === male (not female?)
alert(Person.prototype.gender); // === male (also not female???)


: 위의 결과 stranger는 female로 바뀌었지만 unikys는 여전히 male을 출력하고 있는 것을 확인할 수 있고, unikys의 gender는 그렇다쳐도 직접 stranger.gender를 가져와서 처음에 male이라고 출력하는 것을 확인해봐서 stranger.gender를 설정했는데도 Person.prototyp의 gender는 그대로 값을 유지되고 있다. 이러한 현상이 왜 일어날까 한번 알아보자.



* prototype과 constructor

: 위의 이상한 동작을 알아보기 전에 먼저 내부 메모리 구조가 어떻게 되는지 먼저 알아보자. 이제 ECMAScript에서 정의하고 있는 prototype과 constructor의 링크를 다시 들어가서 한번 읽어보자. 어떠한 내용을 주목하냐면, 정의가 아니라 NOTE 부분을 다시 살펴보자.


http://www.ecma-international.org/ecma-262/5.1/#sec-4.3.4


: constructor의 note는 아래와 같다.


The value of a constructor’s “prototype” property is a prototype object that is used to implement inheritance and shared properties.


: 그리고 prototype의 note는 아래와 같다.


When a constructor creates an object, that object implicitly references the constructor’s “prototype” property for the purpose of resolving property references. The constructor’s “prototype” property can be referenced by the program expression constructor.prototype, and properties added to an object’s prototype are shared, through inheritance, by all objects sharing the prototype. Alternatively, a new object may be created with an explicitly specified prototype by using the Object.create built-in function.


: 이렇게 constructor.prototype이라는 속성이 바로 prototype을 접근할 수 있는 방법이라고 나와있는데, 그럼 이 constructor가 어디서 부여되는지 다시 ECMAScript 스펙을 찾아보자. 어느 부분을 찾아봐야하는지 곰곰히 생각해봐도 생각해내기 어려울테지만 Person이라는 선언을 한 것은 바로 function이었기 때문에 Function이 생성될 때 어떠한 일이 일어나는지 조금 더 자세하게 살펴보면 될 것이다.


http://www.ecma-international.org/ecma-262/5.1/#sec-13.2


: 위의 링크를 보면 Function 객체가 생성될 때 일어나는 일을 설명하고 있다. 따라서 function Person을 선언했을 때 일어나는 일들을 나열하고 있는데, 여기서 다른 부분은 생략하고 17번과 18번을 살펴보면 아래와 같다.


17. Call the [[DefineOwnProperty]] internal method of proto with arguments "constructor", Property Descriptor {[[Value]]: F, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}, and false.

18. Call the [[DefineOwnProperty]] internal method of F with arguments "prototype", Property Descriptor {[[Value]]: proto, { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false}, and false.


: 17번을 보면 proto에 "constructor"라는 속성으로 현재 생성자 함수 F를 부여하는 것을 볼 수 있고, 18번을 보면 F에 "prototype" 속성에 proto를 설정하는 것을 확인할 수 있다. F에 proto를 설정하고 proto에 F를 설정하니 바로 순환구조가 된다. 이것을 브라우져의 개발자 콘솔에서도 쉽게 확인할 수 있다. console.log(Person); 또는 console.log(unikys.constructor)를 해보면 그 안에 내용을 탐색할수가 있는데, 아래와 같은 구조를 확인할 수 있다.




: 이렇게 prototype 과 constructor의 순환 구조를 확인할 수 있다. 이것을 그림으로 나타내면 아래와 같이 할당되어있다는 것을 알 수 있을 것이다. 여기서 위에서 명시되어있는 F는 function Person이고, proto는 Person.prototype에 대입 시켰던 객체이며, F에서는 prototype이라는 속성으로 proto에 접근을 할 수 있으며, proto에서는 constructor라는 속성으로 F에 접근을 할 수 있는 순환 구조이다.



: 그렇다면 여기서 new Person()으로 객체를 생성하게 되면 어떠한 일이 일어나는지 살펴보면 아래 그림과 같이 된다. 여기서 주목할 것은 proto에서 정의된 getName과 getBlog 함수는 새로운 Person 객체에 들어가지 않고 계속 proto에 남아있다는 점이다. 그리고 새로운 Person 객체에서 F를 호출해서 초기화를 하게 되면 F 안에서 this.name과 this.blog를 설정함으로써 그 Person 객체에 name과 blog를 가지게 되는 것이다. 여기서 Implicit link라고 적은 것은 이렇게 Person 객체 안에서 this.getName 접근을 하면 참조는 할 수 있지만 직접 this.getName을 수정하려고 한다면 proto의 getName이 수정되는 것이 아니라 Person 객체에 있는 getName이 추가되거나 수정되는 것이다. 



: 그리고 재미있는 것은 그렇다면 Person 객체에서 F를 접근하려고 한다면 어떻게 해야할까 하는 질문이다. proto에 대한 implicit link가 있기 때문에 this.constructor 또는 위의 예에서 unikys.constructor로 접근하면 proto에 있는 .constructor를 바라보고 F를 접근할 수 있게 되는 것이고, 위의 순환 구조를 따라서 prototype 또한 접근을 할 수 있게 된다.


unikys = new Person();
alert(unikys.constructor === Person);  // === true
alert(unikys.constructor.prototype === Person.prototype);  // === true

: 이렇게 그리고 보면 이제 위의 gender를 설정하던 예에서 동작이 왜 그렇게 되었는지 알 수 있게 된다. 다시 소스를 가져와보면 아래와 같은데, 이 실행 결과는 아래 그림과 같다.


function Person() {};
var unikys = new Person(), stranger = new Person();
Person.prototype.gender = "male";
stranger.gender = "female";




: 위와 같이 stranger.gender를 설정하게 되면 proto의 gender가 바뀌는 것이 아니라 stranger에 gender를 생성하여 저장하게 되기 때문에 Person.prototype.gender는 그대로 유지되고, unikys.gender는 proto의 gender를 참조하기 때문에 male로 남아있게 된다. 따라서 만약 모든 Person 객체를 공통적으로 바꾸고 싶다면 proto에 있는 gender를 바꾸게 되면 모든 Person 객체에 공통되게 바뀌게 될 것이다.


function Person() {};
Person.prototype.gender = "male";
var unikys = new Person(), stranger = new Person();
alert(unikys.gender === "male" && stranger.gender === "male");  // === true;
Person.prototype.gender = "female";
alert(unikys.gender === "female" && stranger.gender === "female");  // === true;


 

* 속성 탐색 순서

: 위와 같은 구조 때문에 자기의 변수를 접근하고자 한다면 일단 자기 자신 객체의 속성부터 찾아서 존재하면 리턴하고, 없으면 자신의 proto에 저장되어있는 속성들을 검사해보고 있으면 리턴 없으면 undefined를 리턴하게 되는 것이다. 여기서 proto는 다른 객체가 될 수 있다는 점을 살펴보면 proto를 또 다른 F와 proto를 가진 객체로 설정하게 된다면 그것이 바로 상속의 기본적인 형태가 되는 것이고, 변수 탐색이 prototype을 따라서 쭉 연결되기 때문에 이것을 "prototype chain"이라고 불리운다. 간단한 상속을 그 유명한(?) Car 예제를 통해서 살펴보면 아래와 같다.


function Car() {
    this.wheel = 4;
    this.beep = "BEEP!";
};
Car.prototype.go = function () {
    alert(this.beep);
};
function Truck() {
    this.wheel = 6;
    this.beep = "HONK!";
};
Truck.prototype = new Car();
function SUV() {
    this.beep = "WANK!";
};
SUV.prototype = new Car();
var truck = new Truck(), suv = new SUV();
alert(truck.wheel === 6 && suv.wheel === 4);  // === true;
alert(truck.beep === "HONK!" && suv.beep === "WANK!");  // === true;
truck.go(); // === "HONK!"
suv.go(); // === "WANK!"


: 각 Truck 함수와 SUV 함수의 prototype을 new Car()로 새로운 객체를 생성하면 거기서 truck.go()로 go 속성을 참조하려고 할 때 다음과 같은 순서로 찾게 되는 것이다.


  1. truck에 go 속성이 있는지 검사
  2. Truck.prototype에 go 속성이 있는지 검사 = new Car()에 속성이 있는지 검사
  3. new Car()에 없으면, 해당 객체의 prototype인 Car.prototype에 go 속성이 있는지 검사
  4. Car.prototype.go 발견

: 이단계들은 객체의 속성을 접근할 때 재귀적으로 계속 해당 객체 -> prototype에 있는지를 검사하는 단계를 거치게 되는 것이다.



* hasOwnProperty의 활용

: 여기서 이제 다시 재조명시켜봐야할 함수가 하나 있다. 바로 모든 객체에 기본적으로 들어있는 hasOwnProperty 함수이다. 이 함수의 역할은 접근하려고하는 속성이 현재 객체에 포함된 것인지 아닌지를 구분하는 함수로, 이 함수를 이용하면 현재 객체의 속성인지 prototype안에 있거나 위와 같이 생성된 prototype chain 에 있는 것인지 구분할 수 있게 도와준다. 이렇게 활용할 예를 살펴보면 for-in 을 이용할 때가 대표적이다. 아래는 간단하게 특정 객체에 어떠한 속성과 값이 있는지 알아보고 싶을 때 for-in을 이용한 예이다.


function Person(name, blog) {
    this.name = name;
    this.blog = blog;
}
Person.prototype.getName = function () {
    return this.name;
};
Person.prototype.getBlog = function () {
    return this.blog;
};
var unikys = new Person("unikys", "unikys.tistory.com");
for (var prop in unikys) {
    console.log("unikys[" + prop + "] = " + unikys[prop]);
}


: 위와 같이 실행하면 아래와 같이 결과가 나온다.



: 이렇게 unikys의 name과 blog 속성 뿐만아니라 unikys의 prototype에 들어있는 getName과 getBlog까지도 출력되는 것을 볼 수 있다. 이러한 현상을 방지하기 위하여 hasOwnProperty를 사용하면 prototype에서 가져오는 속성들을 걸러낼 수 있게 된다.


for (var prop in unikys) {
    if (unikys.hasOwnProperty(prop)) {
        console.log("unikys[" + prop + "] = " + unikys[prop]);
    }
}

: 그럼 아래와 같이 결과가 출력된다.



: 따라서 이렇게 해당 객체의 속성만을 접근을 하고자할 때에는 hasOwnProperty 함수를 이용해서 접근을 하면 좋고, Douglas Crockford가 만들었던 자바스크립트의 코딩 스타일을 점검해주는 JSLint에서도 for-in을 사용할 때 hasOwnProperty로 속성을 점검해줄 것을 권장하고 있다. 지금 당장은 이러한 경우가 언제 필요할지 감이 잘 안올지도 모르지만, 다양한 객체를 활용하는 복잡한 자바스크립트를 개발하게 되면 습관을 들이면 좋을 코딩 습관이다.



* 왜 prototype을 사용해야하는가?

: 사실 굳이 복잡하게 공유하는 prototype에다가 함수를 설정하고 하지 않고 직관적으로 constructor에 직접 this의 속성으로 변수를 추가하듯 함수를 일일이 추가할수도 있다. 그렇다면 constructor를 사용해서 초기화하는 모든 객체들은 해당하는 함수를 가지게 될것이지만 왜 prototype을 사용하는 것이 더 좋을까? 이에 대해서는 예전에 '자바스크립트 라이브러리 만들기'글을 쓰면서 잠깐 다룬 적이 있는데 constructor로 생성하듯 연관배열로 함수를 저장하는 방법과 prototype으로 저장하는 방법을 조금 비교해봤었다.


2012/11/01 - [자바스크립트 라이브러리 만들기] 5. 기본 지식 - 연관 배열과 prototype (클래스 멤버 함수 선언하기)


: 이때에는 막연하게 여러 개의 객체들이 같은 메모리에 함수를 공유한다고 써놨지만 위의 prototype을 참조하고 있는 unikys와 stranger가 나와있는 그림에서 보듯이 prototype이라는 객체 하나가 함수/변수들을 가지고 여러 객체들과 서로 공유를 하는 구조를 가지게 되는 것을 명시적으로, 이론적으로 더욱더 명확하게 알 수 있게 되었을 것이다. 따라서, 만약 여러 객체들을 생성해야하는 상황이라면 이렇게 prototype을 사용할 것을 권장한다.



* prototype의 단점

: 하지만 언제나 만능은 없는 법. prototype의 단점들도 몇가지 꼽을 수가 있는데, 그 중 가장 눈에 띄는 것은 바로 자바스크립트에 익숙하지 않은 사람들은 도무지 봐도 이해를 할 수가 없다는 점이다. 위의 gender 예에서도 그랬지만, 일반 개발자로서는 얼핏봐서는 이해할 수 없는 동작들이 일어나기도 하고, prototype이라는 속성이 자동으로 생성된다는 점과 그 이름 자체 prototype에 거부감을 느끼면서 현기증이 나기도 한다. 하지만 이것은 자바스크립트 개발자로서 위의 내용들을 기본 지식으로 가지고 있으면 해결될 일이다. 위의 단점보다도 더 큰 고칠 수 없는 치명적인 단점이라면 퍼포먼스가 안 좋아질 수 있다는 점이다. 위의 prototype chain을 따라서 먼저 자기 자신이 속성을 가지고 있는지 체크하고 없으면 prototype, 또 없으면 prototype의 prototype 이런식으로 연쇄적으로 검사를 하는 것 자체가 다소 자원 소모적인 검색이기 때문에, 해당 객체에서 자주 사용할 속성이라면 prototype에는 기본값만 놔두고 자기 자신의 속성으로 새로 설정하여 최대한 prototype chain에 깊게 들어가서 검색하는 일을 최소화 시키는 것이 현명한 prototype의 활용법일 것이다.



* 정리

  • Function을 생성할 때 기본적으로 prototype 속성이 생성된다.
  • 이 prototype을 다른 객체로 설정함으로써 다른 객체의 속성들과 함수들을 공유할 수 있다.
  • 객체는 prototype에 implicit link로 연결되어있어 직접 this.constructor.prototype으로 접근하지 않으면 값이 수정되지 않고, 같은 속성명으로 값을 설정할 경우 prototype의 값은 사라진 것이 아니라 가려진 것일 뿐이다.
  • prototype은 객체를 생성함에 있어서 같은 메모리를 공유하므로 메모리 자원을 절약할 수 있다.
  • prototype은 상속의 가장 기본적인 방법으로 활용 가능하다.
  • 하지만 여러 단계의 prototype chain을 만들면 퍼포먼스가 안 좋아질 수 있으므로 긴 prototype chain은 자제하자.


* 다음에는 이번에는 prototype에 대하여 이론적으로 많이 다뤘으니 다음에는 조금 더 실용적인 예와 다른 여러 가지 방석의 객체 상속 방법들에 대하여 알아보자.


[속깊은 자바스크립트 강좌] 객체지향의 기본: prototype 끝.


- 다음 편

2013/10/04 - [속깊은 자바스크립트 강좌] 상속, new와 Object.create의 차이

2013/10/29 - [속깊은 자바스크립트 강좌] 글로벌(전역) 변수와 window 객체

2013/11/06 - [속깊은 자바스크립트 강좌] 변수 선언 방법에 대하여

2016/11/13 - [속깊은 자바스크립트 강좌] 마무리(는 책으로!)



출처 - http://unikys.tistory.com/316


'Language > JAVASCRIPT' 카테고리의 다른 글

프로토타입의 이해 03  (0) 2016.12.23
프로토타입의 이해 02  (0) 2016.12.23
참고 강좌  (0) 2016.12.23
pply(), call() 메서드  (0) 2016.12.15
arguments 객체  (0) 2016.12.15
:

참고 강좌

Language/JAVASCRIPT 2016. 12. 23. 09:17

2012/12/10 - [속깊은 자바스크립트 강좌] 시작 (예고편)

2012/12/17 - [속깊은 자바스크립트 강좌] 자바스크립트의 Scope와 Closure 기초

2013/01/07 - [속깊은 자바스크립트 강좌] function declaration vs function expression 차이점

2013/01/10 - [속깊은 자바스크립트 강좌] 함수를 호출하는 방법과 this의 이해

2013/01/21 - [속깊은 자바스크립트 강좌] Closure의 이해 / 오버로딩 구현하기

2013/01/30 - [속깊은 자바스크립트 강좌] Closure 쉽게 이해하기/실용 예제 소스

2013/02/13 - [속깊은 자바스크립트 강좌] 쉬어가기: 웹 개발 방법론의 변화/자바스크립트의 재발견

2013/02/22 - [속깊은 자바스크립트 강좌] 객체지향의 기본: prototype

2013/10/04 - [속깊은 자바스크립트 강좌] 상속, new와 Object.create의 차이

2013/10/29 - [속깊은 자바스크립트 강좌] 글로벌(전역) 변수와 window 객체

2013/11/06 - [속깊은 자바스크립트 강좌] 변수 선언 방법에 대하여


출처 - http://unikys.tistory.com/382




'Language > JAVASCRIPT' 카테고리의 다른 글

프로토타입의 이해 02  (0) 2016.12.23
프로토타입의 이해 01  (0) 2016.12.23
pply(), call() 메서드  (0) 2016.12.15
arguments 객체  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
:

pply(), call() 메서드

Language/JAVASCRIPT 2016. 12. 15. 16:32

함수의 apply(), call() 메서드

From. 프론트엔드 개발자를 위한 자바스크립트 프로그래밍

함수에는 apply()와 call() 두 가지 메서드가 더 있습니다. 이들 메서드는 모두 소유자인 함수를 호출하면서 this를 넘기는데, 결과적으로는 함수 내부에서 this 객체의 값을 바꾸는 것이나 마찬가지입니다. apply() 메서드는 매개변수로 소유자 함수에 넘길 this와 매개변수 배열으로 받습니다. 두 번째 매개변수는 Array의 인스턴스일 수도 있고 arguement 객체일 수도 있습니다. 다음 예제를 보십시오.

01function sum(num1, num2) {
02    return num1 + num2;
03}
04 
05function callSum1(num1, num2) {
06    return sum.apply(this, arguments);  // arguments 객체를 넘깁니다.
07}
08 
09function callSum2(num1, num2) { // 배열을 넘깁니다.
10    return sum.apply(this, [num1, num2]);
11}
12 
13alert(callSum1(10, 10));    // 20
14alert(callSum2(10, 10));    // 20                          

이 예제에서 callSum1()은 sum()을 호출하면서 자신의 this와 arguments 객체를 매개변수로 넘겼습니다. callSum2() 역시 sum()을 호출하지만 이번에는 arguments 객체가 아니라 매배변수 배열을 넘겼습니다. 두 함수 모두 올바르게 실행됩니다.

call() 메서드도 apply()와 마찬가지로 동작하지만 매개변수를 전달하는 방식이 다릅니다. this가 첫 번째 매개변수인 점은 똑같지만 call()을 사용할 때는 반드시 다음 예제와 같이 매개변수를 각각 나열해야 합니다.

1function sum(num1, num2) {
2    return num1 + num2;
3}
4 
5function callSum(num1, num2) {
6    return sum.call(this, num1, num2);
7}
8 
9alert(callSum(10, 10)); // 20                  

결과는 apply()와 마찬가지입니다. apply()와 call() 중 어느 쪽을 쓸지는 순전히 개발자의 재량이며 매개변수를 전달하기 편리한 방식으로 택하면 됩니다. arguments 객체를 그대로 전달해도 되거나 매개변수로 전달할 데이터가 이미 배열 형태로 준비되어 있다면 apply()가 나을 것이고, 그렇지 않다면 call()이 더 나을 겁니다. 전달할 매개변수가 없다면 두 메서드는 완진히 똑같습니다.

물론 apply()와 call()의 진가는 매개변수를 전달해 호출하는 것이 아니라 this를 바꾸는데 있습니다. 다음 예제를 보십시오.

01window.color = "red";
02var o = {color: "blue"};
03 
04function sayColor() {
05    alert(this.color);
06}
07 
08sayColor(); // red
09 
10sayColor.call(this);    // red
11sayColor.call(window);  // red
12sayColor.call(o)    // blue            

이 예제는 this 객체를 설명할 때 썼던 예제를 조금 고친 겁니다. 이번에도 sayColor()는 전역 함수로 정의되었으므로 전역 스코프에서 호출하면 this.color를 window.color로 평가하여 "red"를 표시합니다. sayColor.call(this)나 sayColor.call(window)와 같이 호출하면 함수 컨텍스트를 명시적으로 전역 스코프로 지정하는 것인데 이렇게 해도 마찬가지로 "red"를 표시합니다. 반면 sayColor.call(o)는 함수의 컨텍스트를 o로 설정하므로 "blue"를 표시합니다.

call()이나 apply()를 써서 스코프를 바꾸면 객체마다 일일히 메서드를 등록하지 않아도 된다는 장점이 있습니다. this 객체를 설명할 때는 o 객체에 직접 sayColor() 메서드를 등록했었지만 이번에는 그렇게 하지 않았습니다.

ECMAScript 5판의 함수에는 bind()라는 메서드도 정의되었습니다. 이 메서드는 새 함수 인스턴스를 만드는데 그 this는 bind()에 전달된 값입니다. 예를 들어 다음 코드를 보십시오.

1window.color = "red";
2var o = {color: "blue"};
3 
4function sayColor() {
5    alert(this.color);
6}
7 
8var objectSayColor = sayColor.bind(o);
9objectSayColor();       // blue

이 예제에서는 sayColor()에서 bind()를 호출하면서 객체 o를 넘겨 objectSayColor()라는 함수를 생성했습니다. objectSayColor() 함수의 this는 o에 묶이므로 전역에서 함수르 호출하더라도 항상 "blue"를 표시합니다.


출처 - http://www.florakid.com/florakid_lib/sub/javascript/apply_call_method.html

'Language > JAVASCRIPT' 카테고리의 다른 글

프로토타입의 이해 01  (0) 2016.12.23
참고 강좌  (0) 2016.12.23
arguments 객체  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
prototypejs  (0) 2013.11.13
:

arguments 객체

Language/JAVASCRIPT 2016. 12. 15. 16:32

arguments 객체는 함수에 전달된 인수에 해당하는 Array같은 객체입니다.

구문

arguments

설명

arguments 객체는 모든 함수 내에서 이용 가능한 지역 변수입니다. arguments 객체를 사용하여 함수 내에서 함수의 인수를 참조할 수 있습니다. 이 객체는 함수에 전달된 각 인수를 위한 항목(entry)을 포함합니다, 첫 번째 항목의 인덱스가 0에서 시작하는. 예를 들어, 함수에 인수 셋이 전달된 경우, 다음과 같이 참조할 수 있습니다:

arguments[0]
arguments[1]
arguments[2]

arguments는 설정될 수도 있습니다:

arguments[1] = 'new value';

arguments 객체는 Array가 아닙니다. Array와 비슷하지만 length 빼고는 어떤 Array 속성도 없습니다. 예를 들어, pop 메서드가 없습니다. 그러나 실제 Array로 변환될 수 있습니다:

var args = Array.prototype.slice.call(arguments);

arguments를 실제 Array로 변환하기 위해 Array.from() 메서드 또는 전개 연산자를 사용할 수도 있습니다:

var args = Array.from(arguments);
var args = [...arguments];

arguments에 slice를 사용하면 일부 JavaScript 엔진(예를 들어 V8 - 자세한 정보는 여기)에서 최적화를 막습니다. 그게 신경 쓰이면, 대신에 arguments 객체를 차례로 반복하여 새로운 배열을 구성해 보세요. 대안은 함수로서 멸시된(despised) Array 생성자를 사용하는 것입니다:

var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));

당신이 형식상 받기로 선언된 것보다 많은 인수로 함수를 호출하는 경우 arguments 객체를 사용할 수 있습니다. 이 기법은 가변 인수가 전달될 수 있는 함수에 유용합니다. 함수에 전달된 인수의 수를 결정하기 위해 arguments.length를 쓰세요, 그 뒤에 arguments 객체를 사용하여 각 인수를 처리하세요. 함수 signature에 매개변수의 수를 결정하기 위해서는, Function.length 속성을 쓰세요.

속성

arguments.callee
현재 실행 중인 함수를 가리킵니다.
arguments.caller 
현재 실행 중인 함수를 호출한 함수를 가리킵니다.
arguments.length
함수에 전달된 인수의 수를 가리킵니다.
arguments[@@iterator]
arguments의 각 인덱스 값을 포함하는 새로운 Array Iterator 객체를 반환합니다.

여러 문자열을 연결하는 함수 정의하기

이 예는 여러 문자열을 연결하는 함수를 정의합니다. 함수의 유일한 형식 인수는 연결할 항목을 구분하는 문자를 지정하는 문자열입니다. 함수는 다음과 같이 정의됩니다:

function myConcat(separator) {
  var args = Array.prototype.slice.call(arguments, 1);
  return args.join(separator);
}

이 함수에 인수를 얼마든지 전달할 수 있으며 리스트 내 항목처럼 각 인수를 사용하여 리스트를 만듭니다.

// "red, orange, blue" 반환
myConcat(", ", "red", "orange", "blue");

// "elephant; giraffe; lion; cheetah" 반환
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// "sage. basil. oregano. pepper. parsley" 반환
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");

HTML 리스트를 만드는 함수 정의하기

이 예는 리스트 HTML을 포함하는 문자열을 만드는 함수를 정의합니다. 함수의 유일한 형식 인수는 리스트가 정렬되지 않은(bulluet(글 머리 기호)가 붙는) 경우 "u" 또는 정렬된(번호가 매겨진) 경우 "o"인 문자열입니다. 함수는 다음과 같이 정의됩니다:

function list(type) {
  var result = "<" + type + "l><li>";
  var args = Array.prototype.slice.call(arguments, 1);
  result += args.join("</li><li>");
  result += "</li></" + type + "l>"; // end list

  return result;
}

이 함수에 인수를 얼마든지 전달할 수 있고, 표시된 유형의 리스트에 항목으로 각 인수를 추가합니다. 예를 들면:

var listHTML = list("u", "One", "Two", "Three");

/* listHTML은:

"<ul><li>One</li><li>Two</li><li>Three</li></ul>"

*/

나머지, 기본 및 비구조화된 매개변수

arguments 객체는 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수와 함께 사용될 수 있습니다.

function foo(...args) {
  return arguments;
}
foo(1, 2, 3); // { "0": 1, "1": 2, "2": 3 }

그러나, 비엄격 함수에서는 mapped arguments 객체는 함수가 어떤 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수든 포함하지 않는 경우에만 제공됩니다. 예를 들어, 기본 매개변수를 사용하는 다음 함수에서는, 100 대신에 10이 반환됩니다:

function bar(a=1) {
  arguments[0] = 100;
  return a;
}
bar(10); // 10

이 예에서, 어떤 나머지 매개변수기본 매개변수 또는 비구조화된 매개변수가 없는 경우에는, 100이 반환됩니다:

function zoo(a) {
  arguments[0] = 100;
  return a;
}
zoo(10); // 100

출처 - https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/arguments

'Language > JAVASCRIPT' 카테고리의 다른 글

참고 강좌  (0) 2016.12.23
pply(), call() 메서드  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
prototypejs  (0) 2013.11.13
마우스 커서 포지션 이동  (0) 2013.05.22
:

구글맵(차트)

Language/JAVASCRIPT 2014. 12. 12. 16:43

https://developers.google.com/chart/

https://developers.google.com/chart/

https://developers.google.com/maps/documentation/javascript/examples/overlay-hideshow?hl=ko

http://using.tistory.com/82

http://roadmaps.kr/grboard/board.php?id=tips&articleNo=19

http://jsfiddle.net/msoliman85/XyFDM/ 


<!DOCTYPE html>
<html>
 
<head>
   
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
   
<meta charset="utf-8">
   
<title>Showing/Hiding overlays</title>
   
<style>
      html
, body, #map-canvas {
       
height: 100%;
       
margin: 0px;
       
padding: 0px
     
}
     
#panel {
       
position: absolute;
       
top: 5px;
       
left: 50%;
       
margin-left: -180px;
       
z-index: 5;
       
background-color: #fff;
       
padding: 5px;
       
border: 1px solid #999;
     
}
   
</style>
   
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
   
<script>
// This example adds hide() and show() methods to a custom overlay's prototype.
// These methods toggle the visibility of the container <div>.
// Additionally, we add a toggleDOM() method, which attaches or detaches the
// overlay to or from the map.

var overlay;

USGSOverlay.prototype = new google.maps.OverlayView();

function initialize() {
 
var myLatLng = new google.maps.LatLng(62.323907, -150.109291);
 
var mapOptions = {
    zoom
: 11,
    center
: myLatLng,
    mapTypeId
: google.maps.MapTypeId.SATELLITE
 
};

 
var map = new google.maps.Map(document.getElementById('map-canvas'),
      mapOptions
);

 
var swBound = new google.maps.LatLng(62.281819, -150.287132);
 
var neBound = new google.maps.LatLng(62.400471, -150.005608);
 
var bounds = new google.maps.LatLngBounds(swBound, neBound);

 
// The photograph is courtesy of the U.S. Geological Survey.
 
var srcImage = 'https://developers.google.com/maps/documentation/javascript/';
  srcImage
+= 'examples/full/images/talkeetna.png';

  overlay
= new USGSOverlay(bounds, srcImage, map);
}

/** @constructor */
function USGSOverlay(bounds, image, map) {

 
// Now initialize all properties.
 
this.bounds_ = bounds;
 
this.image_ = image;
 
this.map_ = map;

 
// Define a property to hold the image's div. We'll
 
// actually create this div upon receipt of the onAdd()
 
// method so we'll leave it null for now.
 
this.div_ = null;

 
// Explicitly call setMap on this overlay
 
this.setMap(map);
}

/**
 * onAdd is called when the map's panes are ready and the overlay has been
 * added to the map.
 */

USGSOverlay.prototype.onAdd = function() {

 
var div = document.createElement('div');
  div
.style.border = 'none';
  div
.style.borderWidth = '0px';
  div
.style.position = 'absolute';

 
// Create the img element and attach it to the div.
 
var img = document.createElement('img');
  img
.src = this.image_;
  img
.style.width = '100%';
  img
.style.height = '100%';
  div
.appendChild(img);

 
this.div_ = div;

 
// Add the element to the "overlayImage" pane.
 
var panes = this.getPanes();
  panes
.overlayImage.appendChild(this.div_);
};

USGSOverlay.prototype.draw = function() {

 
// We use the south-west and north-east
 
// coordinates of the overlay to peg it to the correct position and size.
 
// To do this, we need to retrieve the projection from the overlay.
 
var overlayProjection = this.getProjection();

 
// Retrieve the south-west and north-east coordinates of this overlay
 
// in LatLngs and convert them to pixel coordinates.
 
// We'll use these coordinates to resize the div.
 
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
 
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

 
// Resize the image's div to fit the indicated dimensions.
 
var div = this.div_;
  div
.style.left = sw.x + 'px';
  div
.style.top = ne.y + 'px';
  div
.style.width = (ne.x - sw.x) + 'px';
  div
.style.height = (sw.y - ne.y) + 'px';
};

USGSOverlay.prototype.onRemove = function() {
 
this.div_.parentNode.removeChild(this.div_);
};

// [START region_hideshow]
// Set the visibility to 'hidden' or 'visible'.
USGSOverlay.prototype.hide = function() {
 
if (this.div_) {
   
// The visibility property must be a string enclosed in quotes.
   
this.div_.style.visibility = 'hidden';
 
}
};

USGSOverlay.prototype.show = function() {
 
if (this.div_) {
   
this.div_.style.visibility = 'visible';
 
}
};

USGSOverlay.prototype.toggle = function() {
 
if (this.div_) {
   
if (this.div_.style.visibility == 'hidden') {
     
this.show();
   
} else {
     
this.hide();
   
}
 
}
};

// Detach the map from the DOM via toggleDOM().
// Note that if we later reattach the map, it will be visible again,
// because the containing <div> is recreated in the overlay's onAdd() method.
USGSOverlay.prototype.toggleDOM = function() {
 
if (this.getMap()) {
   
// Note: setMap(null) calls OverlayView.onRemove()
   
this.setMap(null);
 
} else {
   
this.setMap(this.map_);
 
}
};
// [END region_hideshow]

google
.maps.event.addDomListener(window, 'load', initialize);

   
</script>
 
</head>
 
<body>

<!-- [START region_toolbar] -->
<!-- Add an input button to initiate the toggle method on the overlay. -->
   
<div id ="panel">
     
<input type="button" value="Toggle visibility" onclick="overlay.toggle();"></input>
     
<input type="button" value="Toggle DOM attachment" onclick="overlay.toggleDOM();"></input>
   
</div>
<!-- [END region_toolbar] -->
   
<div id="map-canvas"></div>
 
</body>
</html>

맞춤형 오버레이


Google 지도 API V3는 맞춤형 오버레이를 만들 수 있도록 OverlayView 클래스를 제공합니다. OverlayView는 오버레이를 만들 때 구현해야 할 여러 메소드를 제공하는 기본 클래스입니다. 클래스는 지도 상의 위치와 화면 좌표 간에 변환을 가능하게 하는 몇 개의 메소드도 제공합니다. 맞춤형 오버레이를 만들려면 다음과 같이 수행합니다.

  • 맞춤형 객체의 prototype을 google.maps.OverlayView()의 새 인스턴스로 설정합니다. 이렇게 하면 오버레이 클래스를 효과적으로 \'상속\'할 수 있습니다.
  • 맞춤형 오버레이의 생성자를 만들고 초기화 매개변수를 해당 생성자 내의 맞춤형 속성으로 설정합니다.
  • 프로토타입 내에서 onAdd() 메소드를 구현하고 지도에 오버레이를 연결합니다. OverlayView.onAdd()는 지도에 오버레이를 연결할 준비가 된 경우에 호출됩니다.
  • 프로토타입 내에서 draw() 메소드를 구현하고 객체의 시각적 표시를 처리합니다. 마찬가지로 OverlayView.draw()는 객체가 처음 표시되는 경우 호출됩니다.
  • 또한 onRemove() 메소드를 구현하여 오버레이 내에서 추가한 요소를 정리해야 합니다.

다음은 세부 단계에 대한 설명입니다.

오버레이 상속하기


OverlayView를 사용하여 간단한 이미지 오버레이를 만듭니다(V2 API 내의 GGroundOverlay와 유사). 이미지 경계 및 해당 지역의 USGS 이미지를 포함하는USGSOverlay 객체를 만듭니다. var overlay;

function initialize(){
  
var myLatLng =new google.maps.LatLng(62.323907,-150.109291);
  
var myOptions ={
    zoom
:11,
    center
: myLatLng,
    mapTypeId
: google.maps.MapTypeId.SATELLITE
  
};

  
var map =new google.maps.Map(document.getElementById(\"map_canvas\"), myOptions);

  
var swBound =new google.maps.LatLng(62.281819,-150.287132);
  
var neBound =new google.maps.LatLng(62.400471,-150.005608);
  
var bounds =new google.maps.LatLngBounds(swBound, neBound);

  
// Photograph courtesy of the U.S. Geological Survey
  
var srcImage =\'images/talkeetna.png\';
  overlay 
=newUSGSOverlay(bounds, srcImage, map);
} 다음으로 해당 클래스의 생성자를 만들고 전달된 매개변수를 새 객체의 속성으로 초기화합니다. OverlayView에서 USGSOverlay도 명시적으로 상속해야 합니다. 새 클래스의 prototype을 부모 클래스의 인스턴스로 설정하여 이 작업을 수행합니다. 여기서는 부모 클래스를 수정하려 하지 않으므로 부모 클래스 그 자체보다는 인스턴스로 프로토타입을 설정합니다.functionUSGSOverlay(bounds, image, map){

  
// Now initialize all properties.
  
this.bounds_ = bounds;
  
this.image_ = image;
  
this.map_ = map;

  
// We define a property to hold the image\'s
  
// div. We\'ll actually create this div
  
// upon receipt of the add() method so we\'ll
  
// leave it null for now.
  
this.div_ =null;

  
// Explicitly call setMap() on this overlay
  
this.setMap(map);
}

USGSOverlay.prototype =new google.maps.OverlayView();아직까지는 이 오버레이를 오버레이 생성자의 지도에 연결할 수 없습니다. 특히, 모든 지도 페인(객체가 지도에 표시되는 순서 지정)이 사용 가능한지 확인해야 합니다. 편리하게도, API는 이와 같은 경우가 발생했음을 알려주는 도우미 메소드를 제공합니다. 이 메소드는 다음 섹션에서 처리합니다.

오버레이 초기화하기


오버레이가 최초로 인스턴스화되어 표시할 준비가 완료되면 브라우저의 DOM을 사용하여 지도에 연결해야 합니다. API는 오버레이의 onAdd() 메소드를 호출하여 오버레이가 지도에 추가되었음을 표시합니다. 이미지를 포함할 를 만들어 이 메소드를 처리하고 \"\" 요소를 추가하고 이 요소를 에 연결한 다음, 마지막으로 지도의 페인(pane) 중 하나에 오버레이를 연결합니다. 페인(pane)은 DOM 트리에 있는 노드를 말합니다. MapPanes 유형의 페인(pane) 집합은 지도에 있는 여러 레이어의 스택 순서(stacking order)를 지정합니다. 다음과 같은 페인(pane)이 가능하며 아래쪽에서 위쪽으로 쌓여지는 순서로 열거됩니다.

  • MapPanes.mapPane
  • MapPanes.overlayLayer
  • MapPanes.overlayShadow
  • MapPanes.overlayImage
  • MapPanes.floatShadow
  • MapPanes.overlayMouseTarget
  • MapPanes.floatPane

Google은 \'지상 오버레이\' 이미지를 제공하므로 overlayLayer 지도 페인(pane)을 사용합니다. 지도 페인(pane)을 가지고 있으면 객체가 지도 페인에 자식으로 연결됩니다. USGSOverlay.prototype.onAdd =function(){

  
// Note: an overlay\'s receipt of onAdd() indicates that
  
// the map\'s panes are now available for attaching
  
// the overlay to the map via the DOM.

  
// Create the DIV and set some basic attributes.
  
var div = document.createElement(\'DIV\');
  div
.style.border =\"none\";
  div
.style.borderWidth =\"0px\";
  div
.style.position =\"absolute\";

  
// Create an IMG element and attach it to the DIV.
  
var img = document.createElement(\"img\");
  img
.src =this.image_;
  img
.style.width =\"100%\";
  img
.style.height =\"100%\";
  div
.appendChild(img);

  
// Set the overlay\'s div_ property to this DIV
  
this.div_ = div;

  
// We add an overlay to a map via one of the map\'s panes.
  
// We\'ll add this overlay to the overlayImage pane.
  
var panes =this.getPanes();
  panes
.overlayLayer.appendChild(div);
}

오버레이 그리기


위에서 특수한 시각적 표시를 실제로 호출한 것은 아닙니다. API는 지도에 오버레이를 그릴 때마다(처음 추가한 경우 포함) 오버레이에 별도의 draw() 메소드를 호출합니다. 따라서 이 draw() 메소드를 구현하고 getProjection()을 사용하여 오버레이의 MapCanvasProjection를 검색하고 객체의 오른쪽 상단과 왼쪽 하단 지점을 배치할 정확한 좌표를 계산합니다. 여기에서  크기가 조정됩니다. 이렇게 하면 오버레이 생성자에서 지정한 경계와 일치하도록 이미지 크기가 조정됩니다.USGSOverlay.prototype.draw =function(){

  
// Size and position the overlay. We use a southwest and northeast
  
// position of the overlay to peg it to the correct position and size.
  
// We need to retrieve the projection from this overlay to do this.
  
var overlayProjection =this.getProjection();

  
// Retrieve the southwest and northeast coordinates of this overlay
  
// in latlngs and convert them to pixels coordinates.
  
// We\'ll use these coordinates to resize the DIV.
  
var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
  
var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

  
// Resize the image\'s DIV to fit the indicated dimensions.
  
var div =this.div_;
  div
.style.left = sw.x +\'px\';
  div
.style.top = ne.y +\'px\';
  div
.style.width =(ne.x - sw.x)+\'px\';
  div
.style.height =(sw.y - ne.y)+\'px\';
}

오버레이 삭제하기


onRemove() 메소드를 추가하여 지도에서 오버레이를 완전히 삭제할 수도 있습니다. 이 메소드는 오버레이의 map 속성을 null로 설정한 적이 있으면 API에서 자동으로 호출됩니다. USGSOverlay.prototype.onRemove =function(){
  
this.div_.parentNode.removeChild(this.div_);
  
this.div_ =null;
} 

예제 보기(overlay-simple.html) 

오버레이 숨기기 및 표시하기


오버레이를 단순히 만들거나 삭제하는 것이 아니라 숨기거나 표시하려면, 자신의 hide() 및 show() 메소드를 구현하여 오버레이의 가시성을 조정할 수 있습니다. 또는 지도의 DOM에서 오버레이를 분리할 수도 있습니다. 그러나 이 작업에는 비용이 약간 더 듭니다. 그리고 나서 오버레이를 지도의 DOM에 다시 연결하면 오버레이의 onAdd() 메소드가 다시 호출됩니다. 다음 예에서는 hide() 및 show() 메소드를 오버레이의 프로토타입에 추가합니다. 이 프로토타입은 컨테이너 의 가시성을 전환합니다. 또한 오버레이를 지도에 연결하거나 분리하는 toogleDOM() 메소드를 추가합니다. 가시성을 \"hidden\"으로 설정한 다음 toggleDOM()을 통해 DOM에서 지도를 분리할 경우, 지도를 나중에 다시 연결하면 지도는 포함하는 가 오버레이의 onAdd() 메소드에서 다시 만들어지기 때문에 다시 표시됩니다. // Note that the visibility property must be a string enclosed in quotes
USGSOverlay.prototype.hide =function(){
  
if(this.div_){
    
this.div_.style.visibility =\"hidden\";
  
}
}

USGSOverlay.prototype.show =function(){
  
if(this.div_){
    
this.div_.style.visibility =\"visible\";
  
}
}

USGSOverlay.prototype.toggle =function(){
  
if(this.div_){
    
if(this.div_.style.visibility ==\"hidden\"){
      
this.show();
    
}else{
      
this.hide();
    
}
  
}
}

USGSOverlay.prototype.toggleDOM =function(){
  
if(this.getMap()){
    
this.setMap(null);
  
}else{
    
this.setMap(this.map_);
  
}
}

// Now we add an input button to initiate the toggle method 
// on the specific overlay
<div id =\"toolbar\" width=\"100%; height:20px;\" style=\"text-align:center\">
  
<input type=\"button\" value=\"Toggle Visibility\" onclick=\"overlay.toggle();\">input>
  <input type=\"button\" value=\"Toggle DOM Attachment\" onclick=\"overlay.toggleDOM();\">input>
</div>




Google Maps + D3.js

d3.js 2014/02/11 11:08

Google Map위에 D3.js를 이용하여 마커 혹은 차트를 랜더링 하는 방법을 알아보자.


우선 Google Map 객체를 생성해보자.

Google Map 객체는 MapOption 줌레벨, 지도유형 등을 세팅 가능하다.

자세한 사항은 여기를 참고하기 바란다.

1
2
3
4
5
var map = new google.maps.Map(d3.select("#map").node(), {
    zoom: 12,
    center: new google.maps.LatLng(37.556059, 126.91009),
    mapTypeId: google.maps.MapTypeId.ROADMAP
});

여기서는 줌레벨과 초기 지도 센터 위도/경도 정보, 그리고 지도유형을 설정하였다.


이제 지도위에 마커정보(위도/경도)와 오버레이 객체를 생성한다.

지도위에 마커나 차트를 랜더링하기 위해서는 오버레이 객체를 생성해야 한다.

오버레이는 지도 상의 위도/경도 좌표에 연결된 객체를 말한다.

지도를 드래그하거나 확대/축소하면 연결된 오버레이도 함께 움직이며 지도에 '추가'하는 객체를 말한다.

1
2
var overlay = new google.maps.OverlayView();
var data = {"우리집":[126.8998768,37.4639925, 15,],"구로디지털단지역":[126.901472,37.48525, 15,2], /*생략*/};

data는 마커용 라벨정보와 위도/경도 정보 마커크기, 그리고 지하철 노선정보가 있다. 이 데이터를 이용하여 D3.js로 Circle를 랜더링할 수 있으며 이 글에서는 해당 정보에서 위도/경도만 사용하여 Pie Chart를 그려보고자 한다.

이제 오버레이에 Pie Chart를 랜더링 해보자.

1
2
3
4
5
overlay.onAdd = function() {
    var layer = d3.select(this.getPanes().overlayMouseTarget).append("div").attr("class", "stations");
         
    overlay.draw = function() {
        var projection = this.getProjection(), padding = 50;

여기까지 코드를 살펴보면 지도에 오버레이 랜더링할 준비가 되었을 경우(onAdd) stations div를 추가하고

오버레이에 초기 랜더링(draw)해준다. getProjection()은 Map상에 표시할 좌표를 계산하기 위한 메소드이다.

여기서 중요한건 overlayMouseTarget이다. 마커나 차트에 이벤트 바인딩을 하려면 해당 속성을 지정해줘야 한다.


이제 실제 마커할 D3.js소스를 추가해보자. 여기서 Pie Chart는 NVD3.js 라이브러리를 사용하였다.

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
        var marker = layer.selectAll("svg")
            .data(d3.entries(data))
            .each(transform)
            .enter().append("svg:svg")
            .each(transform)
            .attr("class", "marker");
 
        var pieData = [{"key": "One","value" : 29.765957771107} , {"key": "Two","value" : 10} ,{"key": "Three","value" : 32.807804682612} , {"key": "Four","value" : 196.45946739256}];
 
        nv.addGraph(function() {
            var chart = nv.models.pieChart()
                .x(function(d) { return d.key; })
                .y(function(d) { return d.value; })
                .margin({top: 0, right: 0, bottom: 0, left: 0})
                .showLabels(true)
                .labelThreshold(.05)
                .donut(true)
                .showLegend(false);
                           
            marker.datum(pieData).transition().duration(1200).call(chart);
 
            return chart;
        });
        function transform(d) {
            d = new google.maps.LatLng(d.value[1], d.value[0]);
            d = projection.fromLatLngToDivPixel(d);
            return d3.select(this)
                .style("left", (d.x-padding) + "px")
                .style("top", (d.y-padding) + "px");
        }
    }; //overlay.draw end
}; //overlay.onAdd end
overlay.setMap(map);

2번 라인 d3.entries(data)으로 data를 key, value로 변경해준다.

1
[{"key":"우리집","value":[126.8998768,37.4639925,15]},{"key":"구로디지털단지역","value":[126.901472,37.48525,15,2]}];

3번 라인에서 data 갯수만큼 each 메소드이용하여 24-30라인의 transform함수를 호출한다.

transform함수의 역활은 Map상에서 실제 마커될 Pie Chart의 픽셀 위치를 위도/경도를 이용하여 세팅해준다.

8번 라인은 Pie Chart의 Data이다. 10-23라인은 NVD3.js를 이용한 Pie Chart를 추가해준다.


Google Map은 zoom_changed, dragend와 같은 각종 이벤트를 제공한다.

해당 이벤트를 사용하는 방법도 간단하게 살펴보자.

1
2
3
4
5
6
7
8
9
google.maps.event.addListener(map, 'zoom_changed', function() {
    var zoomLevel = map.getZoom();
    var lat_south = map.getBounds().getSouthWest().lat();
    var lat_north = map.getBounds().getNorthEast().lat();
    var lng_west = map.getBounds().getSouthWest().lng();
    var lng_east = map.getBounds().getNorthEast().lng();
    var lat_center = map.getCenter().lat();
    var lng_center = map.getCenter().lng();
});

위 소스를 보면 Google Map에서 zoom_charged 이벤트가 발생할때 Map상에 줌레벨, 위도/경도 정보를 구할 수 있다.

해당 정보를 이용하여 현재 Map상에 표현할 마커나 차트정보를 서버 측에서 구해와 랜더링 할 수 있을 것이다.


참고자료








google.load( 'visualization', '1', { packages:['corechart'] });

function ChartMarker( options ) {
    this.setValues( options );
    
    this.$inner = $('<div>').css({
        position: 'relative',
        left: '-50%', top: '-50%',
        width: options.width,
        height: options.height,
        fontSize: '1px',
        lineHeight: '1px',
        backgroundColor: 'transparent',
        cursor: 'default'
    });

    this.$div = $('<div>')
        .append( this.$inner )
        .css({
            position: 'absolute',
            display: 'none'
        });
};

ChartMarker.prototype = new google.maps.OverlayView;

ChartMarker.prototype.onAdd = function() {
    $( this.getPanes().overlayMouseTarget ).append( this.$div );
};

ChartMarker.prototype.onRemove = function() {
    this.$div.remove();
};

ChartMarker.prototype.draw = function() {
    var marker = this;
    var projection = this.getProjection();
    var position = projection.fromLatLngToDivPixel( this.get('position') );

    this.$div.css({
        left: position.x,
        top: position.y,
        display: 'block'
    })

    this.$inner
        .html( '<img src="' + this.get('image') + '"/>' )
        .click( function( event ) {
            var events = marker.get('events');
            events && events.click( event );
        });
        
    this.chart = new google.visualization.PieChart( this.$inner[0] );
    this.chart.draw( this.get('chartData'), this.get('chartOptions') );
};

function initialize() {
    var latLng = new google.maps.LatLng( 40.708762, -74.006731 );

    var map = new google.maps.Map( $('#map_canvas')[0], {
        zoom: 15,
        center: latLng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    
    var data = google.visualization.arrayToDataTable([
        [ 'Task', 'Hours per Day' ],
        [ 'Work', 1 ],
        [ 'Eat', 9 ]
    ]);
    var color = ['red','blue' ];
    
                 
    var rotation = [ 100, 140];
    for(i=0; i<2; i++){
                    
    var options = {
        fontSize: 8,
        backgroundColor: 'transparent',
        legend: 'none',
         pieStartAngle: rotation[i],
        pieSliceBorderColor: 'transparent',
       slices: {
            0: { color: color[i] },
            1: { color: 'transparent' }
          }        
    };
    var marker = new ChartMarker({
        map: map,
        position: latLng,
        width: '80px',
        height: '80px',
        chartData: data,
        chartOptions: options,
       
        events: {
            click: function( event ) {
                alert( 'Clicked marker' );
            }
        }
    });
}
};

$( initialize );



<script type="text/javascript" src="https://www.google.com/jsapi"></script><script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>


<div id="map_canvas" style="height: 400px; width: 400px"></div>


'Language > JAVASCRIPT' 카테고리의 다른 글

pply(), call() 메서드  (0) 2016.12.15
arguments 객체  (0) 2016.12.15
prototypejs  (0) 2013.11.13
마우스 커서 포지션 이동  (0) 2013.05.22
XMLHttpRequest 고급 기능  (1) 2013.04.29
:

prototypejs

Language/JAVASCRIPT 2013. 11. 13. 17:16

http://prototypejs.org/doc/latest/Prototype/index.html

'Language > JAVASCRIPT' 카테고리의 다른 글

arguments 객체  (0) 2016.12.15
구글맵(차트)  (0) 2014.12.12
마우스 커서 포지션 이동  (0) 2013.05.22
XMLHttpRequest 고급 기능  (1) 2013.04.29
XMLHttpRequest Level 2  (0) 2013.04.29
:

마우스 커서 포지션 이동

Language/JAVASCRIPT 2013. 5. 22. 13:19

function setCaretPosition(ctrl, pos)
{
    if(ctrl.setSelectionRange)
    {
        ctrl.focus();
        ctrl.setSelectionRange(pos,pos);
    }
    else if (ctrl.createTextRange)
    {
        var range = ctrl.createTextRange();
        range.collapse(true);
        range.moveEnd('character', pos);
        range.moveStart('character', pos);
        range.select();
    }
}

'Language > JAVASCRIPT' 카테고리의 다른 글

구글맵(차트)  (0) 2014.12.12
prototypejs  (0) 2013.11.13
XMLHttpRequest 고급 기능  (1) 2013.04.29
XMLHttpRequest Level 2  (0) 2013.04.29
XMLHttpRequest  (0) 2013.04.29
:

XMLHttpRequest 고급 기능

Language/JAVASCRIPT 2013. 4. 29. 19:40
http://msdn.microsoft.com/ko-kr/library/ie/hh673569%28v=vs.85%29.aspx#Enhanced_Event_Support

.NET Framework 3.0

Internet Explorer 10 및 JavaScript를 사용하는 Windows 스토어 앱은 새로운 표준에 대한 지원을 확장하고 일반적인 개발자 시나리오를 손쉽게 지원할 수 있도록 XMLHttpRequest 개체의 몇 가지 고급 기능을 제공합니다. 여기에는 다음과 같은 기능이 포함됩니다.

  • 플러그 인을 사용하지 않고 이미지, 동영상 및 오디오와 같은 이진 파일을 다운로드 및 업로드합니다.
  • 플러그 인을 사용하지 않고 멀티미디어 콘텐츠 스트리밍을 다운로드합니다.
  • XMLHttpRequest 작업 상태를 더 잘 관찰합니다.
  • 다른 브라우저와의 상호 운용성을 개선합니다.

이러한 변경 내용은 다음 섹션에서 자세히 설명합니다.

이진 개체 업로드 및 다운로드

Internet Explorer 10에서는 XMLHttpRequest를 확장하여 이진 데이터를 지원합니다. 부분적으로 이 작업을 위해 파일 API 사양BLOB 인터페이스 지원을 추가합니다.

XMLHttpRequest 개체의 responseType 속성을 "blob"로 설정하면 요청과 관련된 데이터가 이진 데이터로 처리됩니다. 이 경우 다운로드 요청(예: GET)의 응답 속성 값에 영향을 줍니다.

다음 예제는 XMLHttpRequest를 사용하여 이미지를 BLOB 개체로 다운로드한 다음 그 결과를 웹 페이지의 이미지 요소에 할당하는 방법을 보여 줍니다.

JavaScript
var req = new XMLHttpReqest();
xhr.open("GET", "download?name=" + name, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
  if (xhr.readyState == xhr.DONE) {
    var blob = xhr.reponse;
    var image = document.getElementById("my-image");
    image.addEventListener("load", function (evt) {
      URL.revokeObjectURL(evt.target.src);
    }
    image.src = URL.createObjectURL(blob);
  }
}
xhr.send();

다운로드 요청에 대해 responseType 속성을 "ms-stream"으로 설정하면 다음 예제와 같이 콘텐츠를 즉석에서 처리할 수 있습니다.

JavaScript
var req = new XMLHttpReqest();
xhr.open("GET", "download?name=" + name, true);
xhr.responseType = "ms-stream";
xhr.onreadystatechange = function () {
  if (xhr.readyState == xhr.LOADING) {
    var stream = xhr.reponse;
    var video = document.getElementById("my-video");
    video.addEventListener("loadeddata", function (evt) {
      URL.revokeObjectURL(evt.target.src);
    }
    video.src = URL.createObjectURL(stream);
  }
}
xhr.send();

Comet 스트리밍 지원

Internet Explorer 10에서는 다음 예제와 같이 XMLHttpRequest 요청에 대한 응답을 로드하는 동안 responseText 속성을 읽을 수 있도록 하여 multipart HTTP 스트리밍(Comet 스트리밍이라고도 함)을 지원합니다.

JavaScript
xhr.open("GET", url);
xhr.timeout = timeout;
xhr.onreadystatechange = function() {
  if (this.readyState >= 3 && this.status == 200) {
    var content = this.responseText;
    handleContent(content);
  }
}
xhr.send();

이전 Windows Internet Explorer 버전에서는 readyState 속성이 done으로 설정된 경우에만 responseText 속성을 읽을 수 있습니다.

responseText 속성은 현재까지 읽은 응답의 전체 값을 반환합니다. 응답이 수신될 때 개별 응답 패킷을 처리하려면 다음 예제와 같이 progress 이벤트(다음 섹션에 설명됨)를 사용하거나 각 readyStateChange 이벤트 반복의 responseText 길이를 추적할 수 있습니다.

JavaScript
xhr.open("GET", url);
xhr.timeout = timeout;
xhr.onreadystatechange = function() {
  if (typeof this.index == "undefined")
    this.index = 0;
    
  if (this.readyState >= 3 && this.status == 200) {
    var content = this.responseText;
    handleContent( content.substring(this.index) )
    this.index = content.length;
  }
}
xhr.send();

고급 이벤트 지원

Internet Explorer 10에서는 XMLHttpRequest 개체를 확장하여 XMLHttpRequest 수준 2 사양에 지정된 다음 이벤트를 지원합니다.

이벤트설명

loadstart

요청이 시작될 때 발생합니다.

progress

요청이 데이터를 보내거나 받는 동안 서버에서 정의된 간격으로 발생합니다.

abort

요청이 취소될 때(예: abort() 메서드가 호출될 때) 발생합니다.

error

요청이 실패할 때 발생합니다.

load

요청이 성공적으로 완료될 때 발생합니다.

timeout

작성자가 지정한 기간이 경과할 때 발생합니다.

loadend

성공 여부에 관계없이 요청이 완료될 때 발생합니다.

 

XMLHttpRequest 개체의 이벤트 처리는 다음 예제와 같이 DOM 이벤트 수준 3 사양 및 진행률 이벤트 사양에 지정된 모델을 따릅니다.

JavaScript
var xhr = new XMLHttpRequest();
var url = "some-url";

xhr.timeout = 5000;
xhr.addEventListener("timeout", handleTimeout(evt), false);

xhr.onprogress = function(evt) {
  handleEvent("data: " + this.responseText);
  // Calculate progress 
  var str = "";
  if (evt.lengthComputable) {
    var percent = 100 * evt.loaded / evt.total;
    str = percent + "%. Current total size: " + this.responseText.length);
  } else {
    str = "Progress unknown. Current total size: " + this.responseText.length;
  }
  updateProgress(str);
}
xhr.open("GET", url);
xhr.send();

XMLHttpRequest에 대한 CORS(Cross-Origin Resource Sharing)

Internet Explorer 10에서는 XMLHttpRequest(XHR) 개체와 관련하여 CORS(Cross-Origin Resource Sharing)를 새롭게 지원합니다. CORS(Cross-Origin Resource Sharing) 사양에 정의된 CORS는 HTTP 헤더를 사용하여 대개 동일한 사이트 출처 정책으로 제한되는 도메인 간 웹 요청을 가능하게 합니다.

기본적으로 동일한 사이트 출처 정책은 웹 사이트가 다른 도메인에 있는 서버의 리소스를 요청하지 못하도록 합니다. 그러나 XMLHttpRequest(XHR) 요청에 대한 CORS를 지원하는 브라우저는 적절한 관리자가 해당 요청을 허용하도록 선택할 경우 다른 도메인의 리소스에 액세스할 수 있습니다.

웹 페이지가 XHR request를 수행하면 Internet Explorer에서 원본 헤더를 대상 서버로 보냅니다. 헤더에는 요청의 프로토콜 체계(http:// 또는 https://) 및 요청하는 웹 페이지의 호스트 이름이 포함됩니다. 대상 서버는 요청을 승인할 경우 Access-Control-Allow-Origin 헤더를 반환하며 요청을 처리할 수 있습니다.

이제 XMLHttpRequest 개체가 XHR 요청에 권한 부여 메커니즘을 포함할 수 있게 하는 withCredentials 속성을 지원합니다. 자세한 내용은 XMLHttpRequest 수준 2 사양을 참조하세요.

다음 예제와 같이 withCredentials 속성을 사용하여 CORS 지원을 검색할 수 있습니다.

JavaScript
var url = "http://contoso.com/services/"
if( window.XMLHttpRequest ) {
  var oReq = new XMLHttpRequest();
  if( oReq.withCredentials == undefined ) {
    oReq.open("GET", url, true);
    oReq.onload = handleResponse();
    oReq.send( null );
  } else {
  // CORS not support.  Handle fallback
  }
} else { 
  // XMLHttpRequest not supported; handle fallback
}

CORS의 실습 데모는 IE 테스트 드라이브실습: 사이트 간 업로드(영문)를 참조하세요.

관련 항목

DOM(문서 개체 모델)
개발자용 Internet Explorer 10 가이드


'Language > JAVASCRIPT' 카테고리의 다른 글

prototypejs  (0) 2013.11.13
마우스 커서 포지션 이동  (0) 2013.05.22
XMLHttpRequest Level 2  (0) 2013.04.29
XMLHttpRequest  (0) 2013.04.29
자바스크립트  (0) 2013.02.22
:

XMLHttpRequest Level 2

Language/JAVASCRIPT 2013. 4. 29. 18:09

http://www.w3.org/TR/XMLHttpRequest2/#event-xhr-load


W3C

XMLHttpRequest Level 2

W3C Working Draft 17 January 2012

This Version:
http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/
Latest Version:
http://www.w3.org/TR/XMLHttpRequest/
Latest Editor Draft:
http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html
Previous Versions:
http://www.w3.org/TR/2011/WD-XMLHttpRequest2-20110816/
http://www.w3.org/TR/2010/WD-XMLHttpRequest2-20100907/
http://www.w3.org/TR/2009/WD-XMLHttpRequest2-20090820/
http://www.w3.org/TR/2008/WD-XMLHttpRequest2-20080930/
http://www.w3.org/TR/2008/WD-XMLHttpRequest2-20080225/
http://www.w3.org/TR/2007/WD-XMLHttpRequest-20071026/
http://www.w3.org/TR/2007/WD-XMLHttpRequest-20070618/
http://www.w3.org/TR/2007/WD-XMLHttpRequest-20070227/
http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060927/
http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060619/
http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/
Editor:
Anne van Kesteren (Opera Software ASA) <annevk@opera.com>

Abstract

The XMLHttpRequest specification defines an API that provides scripted client functionality for transferring data between a client and a server.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This is the 17 January 2012 W3C Working Draft of XMLHttpRequest Level 2. Please send comments to public-webapps@w3.org (archived) with [XHR] at the start of the subject line.

This document is produced by the Web Applications (WebApps) Working Group. The WebApps Working Group is part of the Rich Web Clients Activity in the W3C Interaction Domain.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document supersedes XMLHttpRequest 1.

Table of Contents

  1. 1 Introduction
    1. 1.1 Specification history
  2. 2 Conformance
    1. 2.1 Dependencies
    2. 2.2 Extensibility
  3. 3 Terminology
  4. 4 Interface XMLHttpRequest
    1. 4.1 Origin and base URL
    2. 4.2 Task sources
    3. 4.3 Constructors
    4. 4.4 Garbage collection
    5. 4.5 Event handlers
    6. 4.6 States
    7. 4.7 Request
      1. 4.7.1 The open() method
      2. 4.7.2 The setRequestHeader() method
      3. 4.7.3 The timeout attribute
      4. 4.7.4 The withCredentials attribute
      5. 4.7.5 The upload attribute
      6. 4.7.6 The send() method
      7. 4.7.7 Infrastructure for the send() method
      8. 4.7.8 The abort() method
    8. 4.8 Response
      1. 4.8.1 The status attribute
      2. 4.8.2 The statusText attribute
      3. 4.8.3 The getResponseHeader() method
      4. 4.8.4 The getAllResponseHeaders() method
      5. 4.8.5 Response entity body
      6. 4.8.6 The overrideMimeType() method
      7. 4.8.7 The responseType attribute
      8. 4.8.8 The response attribute
      9. 4.8.9 The responseText attribute
      10. 4.8.10 The responseXML attribute
    9. 4.9 Events summary
  5. 5 Interface FormData
    1. 5.1 Constructors
    2. 5.2 The append() method
  6. References
    1. Normative references
  7. Acknowledgments

1 Introduction

This section is non-normative.

The XMLHttpRequest object is the ECMAScript HTTP API. [ECMASCRIPT]

The name of the object is XMLHttpRequest for compatibility with the Web, though each component of this name is potentially misleading. First, the object supports any text based format, including XML. Second, it can be used to make requests over both HTTP and HTTPS (some implementations support protocols in addition to HTTP and HTTPS, but that functionality is not covered by this specification). Finally, it supports "requests" in a broad sense of the term as it pertains to HTTP; namely all activity involved with HTTP requests or responses for the defined HTTP methods.

Some simple code to do something with data from an XML document fetched over the network:

function processData(data) {
  // taking care of data
}

function handler() {
  if(this.readyState == this.DONE) {
    if(this.status == 200 &&
       this.responseXML != null &&
       this.responseXML.getElementById('test').textContent) {
      // success!
      processData(this.responseXML.getElementById('test').textContent);
      return;
    }
    // something went wrong
    processData(null);
  }
}

var client = new XMLHttpRequest();
client.onreadystatechange = handler;
client.open("GET", "unicorn.xml");
client.send();

If you just want to log a message to the server:

function log(message) {
  var client = new XMLHttpRequest();
  client.open("POST", "/log");
  client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
  client.send(message);
}

Or if you want to check the status of a document on the server:

function fetchStatus(address) {
  var client = new XMLHttpRequest();
  client.onreadystatechange = function() {
    // in case of network errors this might not give reliable results
    if(this.readyState == this.DONE)
      returnStatus(this.status);
  }
  client.open("HEAD", address);
  client.send();
}

1.1 Specification history

The XMLHttpRequest object was initially defined as part of the WHATWG's HTML effort. (Long after Microsoft shipped an implementation.) It moved to the W3C in 2006. Extensions (e.g. progress events and cross-origin requests) to XMLHttpRequest were developed in a separate draft (XMLHttpRequest Level 2) until end of 2011, at which point the two drafts were merged and XMLHttpRequest became a single entity again from a standards perspective.

Historical discussion can be found in the following mailing list archives:

2 Conformance

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this specification are to be interpreted as described in RFC2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]

2.1 Dependencies

This specification relies on several underlying specifications.

Cross-Origin Resource Sharing

A conforming user agent must support the algorithms of the Cross-Origin Resource Sharing specification. [CORS]

DOM4

A conforming user agent must support at least the subset of the functionality defined in DOM4 that this specification relies upon, such as various exceptions and EventTarget. [DOM]

File API

A conforming user agent must support at least the subset of the functionality defined in File API that this specification relies upon, such as the Blob and File interfaces. [FILEAPI]

HTML

A conforming user agent must support at least the subset of the functionality defined in HTML that this specification relies upon, such as the basics of the Window object and serializing a Document object. [HTML]

HTTP

A conforming user agent must support some version of the HTTP protocol. Requirements regarding HTTP are made throughout the specification. [HTTP]

Progress Events

A conforming user agent must support the Progress Events specification. [PROGRESSEVENTS]

Typed Array

A conforming user agent must support the ArrayBuffer object. [TYPEDARRAY]

Web IDL

A conforming user agent must also be a conforming implementation of the IDL fragments in this specification, as described in the Web IDL specification. [WEBIDL]

XML

A conforming user agent must be a conforming XML processor that reports violations of namespace well-formedness. [XML] [XMLNS]

2.2 Extensibility

User agents, Working Groups, and other interested parties are strongly encouraged to discuss new features on a relevant public forum, preferably public-webapps@w3.org. If this is for some reason not possible prefix the extension in some way. E.g. if company Foo wants to add a proprietary method bar() it could be named fooBar() to prevent clashes with a potential non-proprietary method bar().

3 Terminology

The term user credentials for the purposes of this specification means cookies, HTTP authentication, and client-side SSL certificates. Specifically it does not refer to proxy authentication or the Origin header. [COOKIES]

To deflate a DOMString into a byte sequence means to create a sequence of bytes such that the nth byte of the sequence is equal to the low-order byte of the nth code point in the original DOMString.

To inflate a byte sequence into a DOMString means to create a DOMString such that the nth code point has 0x00 as the high-order byte and the nth byte of the byte sequence as the low-order byte.

4 Interface XMLHttpRequest

[NoInterfaceObject]
interface XMLHttpRequestEventTarget : EventTarget {
  // event handlers
  [TreatNonCallableAsNull] attribute Function? onloadstart;
  [TreatNonCallableAsNull] attribute Function? onprogress;
  [TreatNonCallableAsNull] attribute Function? onabort;
  [TreatNonCallableAsNull] attribute Function? onerror;
  [TreatNonCallableAsNull] attribute Function? onload;
  [TreatNonCallableAsNull] attribute Function? ontimeout;
  [TreatNonCallableAsNull] attribute Function? onloadend;
};

interface XMLHttpRequestUpload : XMLHttpRequestEventTarget {

};

enum XMLHttpRequestResponseType {
  "",
  "arraybuffer",
  "blob",
  "document",
  "json",
  "text"
}

[Constructor]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // event handler
  [TreatNonCallableAsNull] attribute Function? onreadystatechange;

  // states
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  // request
  void open(DOMString method, DOMString url, optional boolean async, optional DOMString? user, optional DOMString? password);
  void setRequestHeader(DOMString header, DOMString value);
           attribute unsigned long timeout;
           attribute boolean withCredentials;
  readonly attribute XMLHttpRequestUpload upload;
  void send();
  void send(ArrayBuffer data);
  void send(Blob data);
  void send(Document data);
  void send(DOMString? data);
  void send(FormData data);
  void abort();

  // response
  readonly attribute unsigned short status;
  readonly attribute DOMString statusText;
  DOMString getResponseHeader(DOMString header);
  DOMString getAllResponseHeaders();
  void overrideMimeType(DOMString mime);
           attribute XMLHttpRequestResponseType responseType;
  readonly attribute any response;
  readonly attribute DOMString responseText;
  readonly attribute Document responseXML;
};

[Constructor]
interface AnonXMLHttpRequest : XMLHttpRequest {
};

4.1 Origin and base URL

Each XMLHttpRequest object has an associated XMLHttpRequest origin and an XMLHttpRequest base URL.

This specification defines their values when the global object is represented by the Window object. When the XMLHttpRequest object is used in other contexts their values will have to be defined as appropriate for that context. That is considered to be out of scope for this specification.

In environments where the global object is represented by the Window object the XMLHttpRequest object has an associated XMLHttpRequest document which is the document associated with the Window object for which the XMLHttpRequest interface object was created.

The XMLHttpRequest document is used to determine the XMLHttpRequest origin and XMLHttpRequest base URL at a later stage.

4.2 Task sources

Each XMLHttpRequest object has its own task source. Namely, the XMLHttpRequest task source.

4.3 Constructors

The XMLHttpRequest object has an associated anonymous flag. If the anonymous flag is set, user credentials and the XMLHttpRequest origin are not exposed when fetching resources. It can only be set to true by using the AnonXMLHttpRequest() constructor.

client = new XMLHttpRequest()
Returns a new XMLHttpRequest object.
client = new AnonXMLHttpRequest()
Returns a new AnonXMLHttpRequest object that has the anonymous flag set.

The XMLHttpRequest() constructor must return a new XMLHttpRequest object.

The AnonXMLHttpRequest() constructor must return a new AnonXMLHttpRequest object with its anonymous flag set.

4.4 Garbage collection

An XMLHttpRequest object must not be garbage collected if its state is OPENED and the send() flag is set, its state is HEADERS_RECEIVED, or its state is LOADING, and one of the following is true:

If an XMLHttpRequest object is garbage collected while its connection is still open, the user agent must cancel any instance of the fetch algorithm opened by this object, discarding any tasks queued for them, and discarding any further data received from the network for them.

4.5 Event handlers

The following are the event handlers (and their corresponding event handler event types) that must be supported on objects implementing an interface that inherits from XMLHttpRequestEventTarget as attributes:

event handler event handler event type
onloadstart loadstart
onprogress progress
onabort abort
onerror error
onload load
ontimeout timeout
onloadend loadend

The following is the event handler (and its corresponding event handler event type) that must be supported as attribute solely by the XMLHttpRequest object:

event handler event handler event type
onreadystatechange readystatechange

4.6 States

client . readyState

Returns the current state.

The XMLHttpRequest object can be in several states. The readyState attribute must return the current state, which must be one of the following values:

UNSENT (numeric value 0)

The object has been constructed.

OPENED (numeric value 1)

The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.

HEADERS_RECEIVED (numeric value 2)

All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available.

LOADING (numeric value 3)

The response entity body is being received.

DONE (numeric value 4)

The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).

The send() flag indicates that the send() method has been invoked. It is initially unset and is used during the OPENED state.

The error flag indicates some type of network error or request abortion. It is initially unset and is used during the DONE state.

4.7 Request

The XMLHttpRequest object holds the following request metadata variables:

synchronous flag
Set when fetching is done synchronously. Initially unset.
request method
The HTTP method used in the request.
request URL
The resolved URL used in the request.
request username
The username used in the request or null if there is no username.
request password
The password used in the request or null if there is no password.
author request headers
A list consisting of HTTP header name/value pairs to be used in the request.
request entity body
The entity body used in the request or null if there is no entity body.
upload complete flag
Set when no more events are to be dispatched on the XMLHttpRequestUpload object. Initially unset.
upload events flag
Set when event listeners are registered on the XMLHttpRequestUpload object to determine whether a preflight request is needed. Initially unset.

The XMLHttpRequest object also has an associated XMLHttpRequestUpload object.

4.7.1 The open() method

client . open(method, url, async, user, password)

Sets the request method, request URL, synchronous flag, request username, and request password.

Throws a "SyntaxError" exception if one of the following is true:

  • method is not a valid HTTP method.
  • url cannot be resolved.
  • url contains the "user:password" format in the userinfo production.

Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK.

Throws an "InvalidAccessError" exception if one of the following is true:

The open(method, url, async, user, password) method must run these steps (unless otherwise indicated):

  1. If there is an associated XMLHttpRequest document run these substeps:

    1. If the XMLHttpRequest document is not fully active, throw an "InvalidStateError" exception and terminate the overall set of steps.

    2. Let XMLHttpRequest base URL be the document base URL of the XMLHttpRequest document.

    3. Let XMLHttpRequest origin be the origin of the XMLHttpRequest document and let it be a globally unique identifier if the anonymous flag is set.

  2. If any code point in method is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating method it does not match the Method token production, throw a "SyntaxError" exception and terminate these steps. Otherwise let method be the result of deflating method.

  3. If method is a case-insensitive match for CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE, or TRACK subtract 0x20 from each byte in the range 0x61 (ASCII a) to 0x7A (ASCII z).

    If it does not match any of the above, it is passed through literally, including in the final request.

  4. If method is a case-sensitive match for CONNECT, TRACE, or TRACK, throw a "SecurityError" exception and terminate these steps.

    Allowing these methods poses a security risk. [HTTPVERBSEC]

  5. Let url be a URL with character encoding UTF-8.

  6. Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError" exception and terminate these steps.

  7. Drop <fragment> from url.

  8. If the "user:password" format in the userinfo production is not supported for the relevant <scheme> and url contains this format, throw a "SyntaxError" and terminate these steps.

  9. If url contains the "user:password" format let temp user be the user part and temp password be the password part.

  10. If url just contains the "user" format let temp user be the user part.

  11. Let async be the value of the async argument or true if it was omitted.

    If async is false, there is an associated XMLHttpRequest document and either the timeout attribute value is not zero, the withCredentials attribute value is true, or the responseType attribute value is not the empty string, throw an "InvalidAccessError" exception and terminate these steps.

  12. If the user argument was not omitted follow these sub steps:

    1. If user is not null and the origin of url is not same origin with the XMLHttpRequest origin, throw an "InvalidAccessError" exception and terminate the overall set of steps.

    2. Let temp user be user.

    These steps override anything that may have been set by the url argument.

  13. If the password argument was not omitted follow these sub steps:

    1. If password is not null and the origin of url is not same origin with the XMLHttpRequest origin, throw an "InvalidAccessError" exception and terminate the overall set of steps.

    2. Let temp password be password.

    These steps override anything that may have been set by the url argument.

  14. Terminate the abort() algorithm.

  15. Terminate the send() algorithm.

  16. The user agent should cancel any network activity for which the object is responsible.

  17. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove them.

  18. Set variables associated with the object as follows:

  19. Change the state to OPENED.

  20. Fire an event named readystatechange.

4.7.2 The setRequestHeader() method

client . setRequestHeader(header, value)

Appends an header to the list of author request headers, or if header is already in the list of author request headers, combines its value with value.

Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.

Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value is not a valid HTTP header field value.

As indicated in the algorithm below certain headers cannot be set and are left up to the user agent. In addition there are certain other headers the user agent will take control of if they are not set by the author as indicated at the end of the send() method section.

For non same origin requests using the HTTP GET method a preflight request is made when headers other than Accept and Accept-Language are set.

The setRequestHeader(header, value) method must run these steps:

  1. If the state is not OPENED, throw an "InvalidStateError" exception and terminate these steps.

  2. If the send() flag is set, throw an "InvalidStateError" exception and terminate these steps.

  3. If any code point in header is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating header it does not match the field-name production, throw a "SyntaxError" exception and terminate these steps. Otherwise let header be the result of deflating header.

  4. If any code point in value is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating value it does not match the field-value production, throw a "SyntaxError" exception and terminate these steps. Otherwise let value be the result of deflating value.

    The empty string is legal and represents the empty header value.

  5. Terminate these steps if header is a case-insensitive match for one of the following headers:

    • Accept-Charset
    • Accept-Encoding
    • Access-Control-Request-Headers
    • Access-Control-Request-Method
    • Connection
    • Content-Length
    • Cookie
    • Cookie2
    • Content-Transfer-Encoding
    • Date
    • Expect
    • Host
    • Keep-Alive
    • Origin
    • Referer
    • TE
    • Trailer
    • Transfer-Encoding
    • Upgrade
    • User-Agent
    • Via

    … or if the start of header is a case-insensitive match for Proxy- or Sec- (including when header is just Proxy- or Sec-).

    The above headers are controlled by the user agent to let it control those aspects of transport. This guarantees data integrity to some extent. Header names starting with Sec- are not allowed to be set to allow new headers to be minted that are guaranteed not to come from XMLHttpRequest.

  6. If header is not in the author request headers list append header with its associated value to the list and terminate these steps.

  7. If header is in the author request headers list either use multiple headers, combine the values or use a combination of those (section 4.2, RFC 2616). [HTTP]

See also the send() method regarding user agent header handling for caching, authentication, proxies, and cookies.

Some simple code demonstrating what happens when setting the same header twice:

// The following script:
var client = new XMLHttpRequest();
client.open('GET', 'demo.cgi');
client.setRequestHeader('X-Test', 'one');
client.setRequestHeader('X-Test', 'two');
client.send();

// …results in the following header being sent:
X-Test: one, two

4.7.3 The timeout attribute

client . timeout

The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout.

When set: throws an "InvalidAccessError" exception if the synchronous flag is set when there is an associated XMLHttpRequest document.

The timeout attribute must return its value. Initially its value must be zero.

Setting the timeout attribute must run these steps:

  1. If there is an associated XMLHttpRequest document and the synchronous flag is set, throw an "InvalidAccessError" exception and terminate these steps.

  2. Set its value to the new value.

This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative to the start of fetching.

4.7.4 The withCredentials attribute

client . withCredentials

True when user credentials are to be included in a cross-origin request. False when they are to be excluded in a cross-origin request and when cookies are to be ignored in its response. Initially false.

When set: throws an "InvalidStateError" exception if the state is not UNSENT or OPENED, or if the send() flag is set.

When set: throws an "InvalidAccessError" exception if either the synchronous flag is set when there is an associated XMLHttpRequest document or if the anonymous flag is set.

The withCredentials attribute must return its value. Initially its value must be false.

Setting the withCredentials attribute must run these steps:

  1. If the state is not UNSENT or OPENED, throw an "InvalidStateError" exception and terminate these steps.

  2. If the send() flag is set, throw an "InvalidStateError" exception and terminate these steps.

  3. If the anonymous flag is set, throw an "InvalidAccessError" exception and terminate these steps.

  4. If there is an associated XMLHttpRequest document and the synchronous flag is set, throw an "InvalidAccessError" exception and terminate these steps.

  5. Set the withCredentials attribute's value to the given value.

The withCredentials attribute has no effect when fetching same-origin resources.

4.7.5 The upload attribute

client . upload

Returns the associated XMLHttpRequestUpload object.

The upload attribute must return the associated XMLHttpRequestUpload object.

4.7.6 The send() method

client . send(data)

Initiates the request. The optional argument provides the request entity body. The argument is ignored if request method is GET or HEAD.

Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set.

The send(data) method must run these steps (unless otherwise noted). This algorithm can be terminated by invoking the open() or abort() method. When it is terminated the user agent must terminate the algorithm after finishing the step it is on.

The send() algorithm can only be terminated if the synchronous flag is unset and only after the method call has returned.

  1. If the state is not OPENED, throw an "InvalidStateError" exception and terminate these steps.

  2. If the send() flag is set, throw an "InvalidStateError" exception and terminate these steps.

  3. If the request method is a case-sensitive match for GET or HEAD act as if data is null.

    If the data argument has been omitted or is null, do not include a request entity body and go to the next step.

    Otherwise, let encoding be null, mime type be null, and then follow these rules:

    If data is a ArrayBuffer

    Let the request entity body be the raw data represented by data.

    If data is a Blob

    If the object's type attribute is not the empty string let mime type be its value.

    Let the request entity body be the raw data represented by data.

    If data is a Document

    Let encoding be the preferred MIME name of the character encoding of data. If encoding is UTF-16 change it to UTF-8.

    Let mime type be "application/xml" or "text/html" if Document is an HTML document, followed by ";charset=", followed by encoding.

    Let the request entity body be the result of getting the innerHTML attribute on data converted to Unicode and encoded as encoding. Re-throw any exception this throws.

    In particular, if the document cannot be serialized an "InvalidStateError" exception is thrown.

    Subsequent changes to the Document have no effect on what is transferred.

    If data is a string

    Let encoding be UTF-8.

    Let mime type be "text/plain;charset=UTF-8".

    Let the request entity body be data converted to Unicode and encoded as UTF-8.

    If data is a FormData

    Let the request entity body be the result of running the multipart/form-data encoding algorithm with data as form data set and with UTF-8 as the explicit character encoding.

    Let mime type be the concatenation of "multipart/form-data;", a U+0020 SPACE character, "boundary=", and the multipart/form-data boundary string generated by the multipart/form-data encoding algorithm.

    If a Content-Type header is in author request headers and its value is a valid MIME type that has a charset parameter whose value is not a case-insensitive match for encoding, and encoding is not null, set all the charset parameters of that Content-Type header to encoding.

    If no Content-Type header is in author request headers and mime type is not null, append a Content-Type header with value mime type to author request headers.

  4. If the synchronous flag is set, release the storage mutex.

  5. If the synchronous flag is unset and one or more event listeners are registered on the XMLHttpRequestUpload object, set the upload events flag.

  6. Unset the error flag.

  7. Set the upload complete flag if there is no request entity body or if the request entity body is empty.

  8. If the synchronous flag is unset, run these substeps:

    1. Set the send() flag.

    2. Fire an event named readystatechange.

      The state does not change. The event is dispatched for historical reasons.

    3. Fire a progress event named loadstart.

    4. If the upload complete flag is unset, fire a progress event named loadstart on the XMLHttpRequestUpload object.

    5. Return the send() method call, but continue running the steps in this algorithm.

  9. If the XMLHttpRequest origin and the request URL are same origin

    These are the same-origin request steps.

    Fetch the request URL from origin XMLHttpRequest origin, with the synchronous flag set if the synchronous flag is set, using HTTP method request method, user request username (if non-null) and password request password (if non-null), taking into account the request entity body, list of author request headers and the rules listed at the end of this section.

    If the synchronous flag is set

    While making the request also follow the same-origin request event rules.

    The send() method call will now be returned by virtue of this algorithm ending.

    If the synchronous flag is unset

    Make upload progress notifications.

    Make progress notifications.

    While processing the request, as data becomes available and when the user interferes with the request, queue tasks to update the response entity body and follow the same-origin request event rules.

    Otherwise

    These are the cross-origin request steps.

    Make a cross-origin request, passing these as parameters:

    request URL
    The request URL.
    request method
    The request method.
    author request headers
    The list of author request headers.
    request entity body
    The request entity body.
    source origin
    The XMLHttpRequest origin.
    credentials flag
    The withCredentials attribute's value.
    force preflight flag
    True if the upload events flag is set, or false otherwise.

    Request username and request password are always ignored as part of a cross-origin request; including them would allow a site to perform a distributed password search. However, user agents will include user credentials in the request (if the user has any and if withCredentials is true).

    If the synchronous flag is set

    While making the request also follow the cross-origin request event rules.

    The send() method call will now be returned by virtue of this algorithm ending.

    If the synchronous flag is unset

    While processing the request, as data becomes available and when the end user interferes with the request, queue tasks to update the response entity body and follow the cross-origin request event rules.


If the user agent allows the end user to configure a proxy it should modify the request appropriately; i.e., connect to the proxy host instead of the origin server, modify the Request-Line and send Proxy-Authorization headers as specified.


If the user agent supports HTTP Authentication and Authorization is not in the list of author request headers, it should consider requests originating from the XMLHttpRequest object to be part of the protection space that includes the accessed URIs and send Authorization headers and handle 401 Unauthorized requests appropriately.

If authentication fails, XMLHttpRequest origin and the request URL are same origin, Authorization is not in the list of author request headers, request username is null, and request password is null, user agents should prompt the end user for their username and password.

Otherwise, if authentication fails, user agents must not prompt the end user for their username and password. [HTTPAUTH]

End users are not prompted for various cases so that authors can implement their own user interface.


If the user agent supports HTTP State Management it should persist, discard and send cookies (as received in the Set-Cookie response header, and sent in the Cookie header) as applicable. [COOKIES]


If the user agent implements a HTTP cache it should respect Cache-Control headers in author request headers (e.g. Cache-Control: no-cache bypasses the cache). It must not send Cache-Control or Pragma request headers automatically unless the end user explicitly requests such behavior (e.g. by reloading the page).

For 304 Not Modified responses that are a result of a user agent generated conditional request the user agent must act as if the server gave a 200 OK response with the appropriate content. The user agent must allow author request headers to override automatic cache validation (e.g. If-None-Match or If-Modified-Since), in which case 304 Not Modified responses must be passed through. [HTTP]


If the user agent implements server-driven content-negotiation it must follow these constraints for the Accept and Accept-Language request headers:

Responses must have the content-encodings automatically decoded. [HTTP]


Besides the author request headers, user agents should not include additional request headers other than those mentioned above or other than those authors are not allowed to set using setRequestHeader(). This ensures that authors have a predictable API.

4.7.7 Infrastructure for the send() method

The same-origin request event rules are as follows:

If the response has an HTTP status code of 301, 302, 303, or 307

If the redirect violates infinite loop precautions this is a network error.

Otherwise, run these steps:

  1. Set the request URL to the URL conveyed by the Location header.

  2. If the XMLHttpRequest origin and the origin of request URL are same origin transparently follow the redirect while observing the same-origin request event rules.

  3. Otherwise, follow the cross-origin request steps and terminate the steps for this algorithm.

HTTP places requirements on the user agent regarding the preservation of the request method and request entity body during redirects, and also requires end users to be notified of certain kinds of automatic redirections.

If the end user cancels the request

This is an abort error.

If there is a network error

In case of DNS errors, TLS negotiation failure, or other type of network errors, this is a network error. Do not request any kind of end user interaction.

This does not include HTTP responses that indicate some type of error, such as HTTP status code 410.

If timeout is not 0 and since the request started the amount of milliseconds specified by timeout has passed

This is a timeout error.

Once all HTTP headers have been received, the synchronous flag is unset, and the HTTP status code of the response is not 301, 302, 303, or 307

Switch to the HEADERS_RECEIVED state.

Once the first byte (or more) of the response entity body has been received and the synchronous flag is unset
If there is no response entity body and the synchronous flag is unset

Switch to the LOADING state.

Once the whole response entity body has been received
If there is no response entity body and the state is LOADING
If there is no response entity body and the synchronous flag is set

Switch to the DONE state.


The cross-origin request event rules are as follows:

If the cross-origin request status is preflight complete and the synchronous flag is unset

Make upload progress notifications.

If the cross-origin request status is network error

This is a network error.

If the cross-origin request status is abort error

This is an abort error.

If timeout is not 0 and since the request started the amount of milliseconds specified by timeout has passed

This is a timeout error.

Once all HTTP headers have been received, the cross-origin request status is success, and the synchronous flag is unset

Switch to the HEADERS_RECEIVED state.

Make progress notifications.

Once the first byte (or more) of the response entity body has been received, the cross-origin request status is success, and the synchronous flag is unset
If there is no response entity body, the cross-origin request status is success, and the synchronous flag is unset

Switch to the LOADING state.

Once the whole response entity body has been received and the cross-origin request status is success
If there is no response entity body, the cross-origin request status is success, and the state is LOADING
If there is no response entity body, the cross-origin request status is success, and the synchronous flag is set

Switch to the DONE state.


When something is said to be a network error run the request error steps for exception "NetworkError" and event error.

When something is said to be an abort error run the request error steps for exception "AbortError" and event abort.

When something is said to be an timeout error run the request error steps for exception "TimeoutError" and event timeout.

When something is said to be a request error for exception exception and event event run these steps:

  1. The user agent should cancel any network activity for which the object is responsible.

  2. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove them.

  3. Set the the error flag.

  4. Change the state to DONE.

  5. If the synchronous flag is set, throw an exception exception and terminate the overall set of steps.

  6. Fire an event named readystatechange.

    At this point it is clear that the synchronous flag is unset.

  7. If the upload complete flag is unset, follow these substeps:

    1. Set the upload complete flag.

    2. Fire a progress event named event on the XMLHttpRequestUpload object.

    3. Fire a progress event named loadend on the XMLHttpRequestUpload object.

  8. Fire a progress event named event.

  9. Fire a progress event named loadend.


When it is said to switch to the HEADERS_RECEIVED state run these steps:

  1. Change the state to HEADERS_RECEIVED.

  2. Fire an event named readystatechange.

When it is said to switch to the LOADING state run these steps:

  1. Change the state to LOADING.

  2. Fire an event named readystatechange.

When it is said to switch to the DONE state run these steps:

  1. If the synchronous flag is set, update the response entity body.

  2. Unset the synchronous flag.

  3. Change the state to DONE.

  4. Fire an event named readystatechange.

  5. Fire a progress event named load.

  6. Fire a progress event named loadend.


When it is said to make progress notifications, while the download is progressing, queue a task to fire a progress event named progress about every 50ms or for every byte received, whichever is least frequent.


When it is said to make upload progress notifications run these steps:

4.7.8 The abort() method

client . abort()
Cancels any network activity.

The abort() method must run these steps (unless otherwise noted). This algorithm can be terminated by invoking the open() method. When it is terminated the user agent must terminate the algorithm after finishing the step it is on.

The abort() algorithm can only be terminated by invoking open() from an event handler.

  1. Terminate the send() algorithm.

  2. The user agent should cancel any network activity for which the object is responsible.

  3. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove them.

  4. Set the error flag.

  5. Unset the synchronous flag.

  6. If the state is UNSENT, OPENED with the send() flag being unset, or DONE go to the next step.

    Otherwise run these substeps:

    1. Change the state to DONE.

    2. Unset the send() flag.

    3. Fire an event named readystatechange.

    4. Fire a progress event named abort.

    5. Fire a progress event named loadend.

    6. If the upload complete flag is false run these substeps:

      1. Set the upload complete flag to true.

      2. Fire a progress event named abort on the XMLHttpRequestUpload object.

      3. Fire a progress event named loadend on the XMLHttpRequestUpload object.

  7. Change the state to UNSENT.

    No readystatechange event is dispatched.

4.8 Response

4.8.1 The status attribute

client . status

Returns the HTTP status code.

The status attribute must return the result of running these steps:

  1. If the state is UNSENT or OPENED, return 0 and terminate these steps.

  2. If the error flag is set, return 0 and terminate these steps.

  3. Return the HTTP status code.

4.8.2 The statusText attribute

client . statusText

Returns the HTTP status text.

The statusText attribute must return the result of running these steps:

  1. If the state is UNSENT or OPENED, return the empty string and terminate these steps.

  2. If the error flag is set, return the empty string and terminate these steps.

  3. Return the HTTP status text.

4.8.3 The getResponseHeader() method

client . getResponseHeader(header)

Returns the header field value from the response of which the field name matches header, unless the field name is Set-Cookie or Set-Cookie2.

The getResponseHeader(header) method must run these steps:

  1. If the state is UNSENT or OPENED, return null and terminate these steps.

  2. If the error flag is set, return null and terminate these steps.

  3. If any code point in header is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS, return null and terminate these steps.

  4. Let header be the result of deflating header.

  5. If header is a case-insensitive match for Set-Cookie or Set-Cookie2, return null and terminate these steps.

  6. If header is a case-insensitive match for multiple HTTP response headers, return the inflated values of these headers as a single concatenated string separated from each other by a U+002C COMMA U+0020 SPACE character pair and terminate these steps.

  7. If header is a case-insensitive match for a single HTTP response header, return the inflated value of that header and terminate these steps.

  8. Return null.

The Cross-Origin Resource Sharing specification filters the headers that are exposed by getResponseHeader() for non same-origin requests. [CORS]

For the following script:

var client = new XMLHttpRequest();
client.open("GET", "unicorns-are-teh-awesome.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == 2) {
    print(client.getResponseHeader("Content-Type"));
  }
}

The print() function will get to process something like:

text/plain; charset=UTF-8

4.8.4 The getAllResponseHeaders() method

client . getAllResponseHeaders()

Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.

The getAllResponseHeaders() method must run these steps:

  1. If the state is UNSENT or OPENED, return the empty string and terminate these steps.

  2. If the error flag is set, return the empty string and terminate these steps.

  3. Return all the HTTP headers, excluding headers that are a case-insensitive match for Set-Cookie or Set-Cookie2, inflated, as a single string, with each header line separated by a U+000D CR U+000A LF pair, excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE pair.

The Cross-Origin Resource Sharing specification filters the headers that are exposed by getAllResponseHeaders() for non same-origin requests. [CORS]

For the following script:

var client = new XMLHttpRequest();
client.open("GET", "narwhals-too.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == 2) {
    print(this.getAllResponseHeaders());
  }
}

The print() function will get to process something like:

Date: Sun, 24 Oct 2004 04:58:38 GMT
Server: Apache/1.3.31 (Unix)
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8

4.8.5 Response entity body

The response MIME type is the MIME type the Content-Type header contains excluding any parameters, or null if the response header can not be parsed or was omitted. The override MIME type is initially null and can get a value if overrideMimeType() is invoked. Final MIME type is the override MIME type unless that is null in which case it is the response MIME type.

The response charset is the value of the charset parameter of the Content-Type header or null if there was no charset parameter or the header could not be parsed or was omitted. The override charset is initially null and can get a value if overrideMimeType() is invoked. Final charset is the override charset unless that is null in which case it is the response charset.


The response entity body is the fragment of the entity body of the response received so far (LOADING) or the complete entity body of the response (DONE). If the response does not have an entity body, the response entity body is null.

The response entity body is updated as part of the send() algorithm.


The arraybuffer response entity body is an ArrayBuffer representing the response entity body. If the arraybuffer response entity body has no value assigned to it let it be the return value of the following algorithm:

  1. If the response entity body is null, return an empty ArrayBuffer object and terminate these steps.

  2. Return an ArrayBuffer object representing the response entity body.

The blob response entity body is a Blob representing the response entity body. If the blob response entity body has no value assigned to it let it be the return value of the following algorithm:

  1. If the response entity body is null, return an empty Blob object and terminate these steps.

  2. Return a Blob object representing the response entity body.

The document response entity body is either a document representing the response entity body or null. If it is a document, its origin is the XMLHttpRequest origin. If the document response entity body has no value assigned to it let it be the return value of the following algorithm:

  1. If the response entity body is null, return null and terminate these steps.

  2. If final MIME type is not null, text/html, text/xml, application/xml, or does not end in +xml, return null and terminate these steps.

  3. If responseType is the empty string and final MIME type is text/html, return null and terminate these steps.

    This is restricted to responseType being "document" in order to prevent breaking legacy content.

  4. If final MIME type is text/html let, document be a document that represents the response entity body parsed following the rules set forth in the HTML specification for an HTML parser with scripting disabled. [HTML]

  5. Otherwise, let document be a document that represents the result of parsing the response entity body following the rules set forth in the XML specifications. If that fails (unsupported character encoding, namespace well-formedness error, etc.), return null and terminate these steps. [XML] [XMLNS]

    Scripts in the resulting document tree will not be executed, resources referenced will not be loaded and no associated XSLT will be applied.

  6. Return document.

The JSON response entity body is an ECMAScript value representing the response entity body. The JSON response entity body is the return value of the following algorithm:

  1. Let JSON text be the response entity body decoded using UTF-8. Remove one leading U+FEFF BYTE ORDER MARK character, if present.

  2. Return the result of invoking the parse function of the JSON object defined in ECMAScript, with JSON text as its only argument, or null if that function throws an exception. [ECMASCRIPT]

The text response entity body is a string representing the response entity body. The text response entity body is the return value of the following algorithm:

  1. If the response entity body is null, return the empty string and terminate these steps.

  2. Let charset be the final charset.

  3. Let mime be the final MIME type.

  4. If responseType is the empty string, charset is null, and mime is either null, text/xml, application/xml or ends in +xml, use the rules set forth in the XML specifications to determine the character encoding. Let charset be the determined character encoding. [XML] [XMLNS]

    This is restricted to responseType being the empty string to keep the non-legacy responseType value "text" simple.

  5. If charset is null then, for each of the rows in the following table, starting with the first one and going down, if the first bytes of bytes match the bytes given in the first column, then let charset be the encoding given in the cell in the second column of that row. If there is no match charset remains null.

    Bytes in Hexadecimal Description
    FE FF UTF-16BE BOM
    FF FE UTF-16LE BOM
    EF BB BF UTF-8 BOM
  6. If charset is null let charset be UTF-8.

  7. Return the result of decoding the response entity body using charset. Replace bytes or sequences of bytes that are not valid according to the charset with a single U+FFFD REPLACEMENT CHARACTER character. Remove one leading U+FEFF BYTE ORDER MARK character, if present.

Authors are strongly encouraged to always encode their resources using UTF-8.

4.8.6 The overrideMimeType() method

client . overrideMimeType(mime)

Sets the Content-Type header for the response to mime.

Throws an "InvalidStateError" exception if the state is LOADING or DONE.

Throws a "SyntaxError" exception if mime is not a valid media type.

The overrideMimeType(mime) method must run these steps:

  1. If the state is LOADING or DONE, throw an "InvalidStateError" exception and terminate these steps.

  2. If parsing mime analogously to the value of the Content-Type headers fails, throw a "SyntaxError" exception and terminate these steps.

  3. If a MIME type is successfully parsed set override MIME type to that MIME type, excluding any parameters.

  4. If a charset parameter is successfully parsed set override charset to its value.

4.8.7 The responseType attribute

client . responseType [ = value ]

Returns the response type.

Can be set to change the response type. Values are: the empty string (default), "arraybuffer", "blob", "document", "json", and "text".

When set: throws an "InvalidStateError" exception if the state is LOADING or DONE.

When set: throws an "InvalidAccessError" exception if the synchronous flag is set and there is an associated XMLHttpRequest document.

The responseType attribute must return its value. Initially its value must be the empty string.

Setting the responseType attribute must run these steps:

  1. If the state is LOADING or DONE, throw an "InvalidStateError" exception and terminate these steps.

  2. If there is an associated XMLHttpRequest document and the synchronous flag is set, throw an "InvalidAccessError" exception and terminate these steps.

  3. Set the responseType attribute's value to the given value.

4.8.8 The response attribute

client . response

Returns the response entity body.

The response attribute must return the result of running these steps:

If responseType is the empty string or "text"
  1. If the state is not LOADING or DONE, return the empty string and terminate these steps.

  2. If the error flag is set, return the empty string and terminate these steps.

  3. Return the text response entity body.

Otherwise
  1. If the state is not DONE, return null and terminate these steps.

  2. If the error flag is set, return null and terminate these steps.

  3. If responseType is "arraybuffer"

    Return the arraybuffer response entity body.

    If responseType is "blob"

    Return the blob response entity body.

    If responseType is "document"

    Return the document response entity body.

    If responseType is "json"

    Return the JSON response entity body.

4.8.9 The responseText attribute

client . responseText

Returns the text response entity body.

Throws an "InvalidStateError" exception if responseType is not the empty string or "text".

The responseText attribute must return the result of running these steps:

  1. If responseType is not the empty string or "text", throw an "InvalidStateError" exception and terminate these steps.

  2. If the state is not LOADING or DONE, return the empty string and terminate these steps.

  3. If the error flag is set, return the empty string and terminate these steps.

  4. Return the text response entity body.

4.8.10 The responseXML attribute

client . responseXML

Returns the document response entity body.

Throws an "InvalidStateError" exception if responseType is not the empty string or "document".

The responseXML attribute must return the result of running these steps:

  1. If responseType is not the empty string or "document", throw an "InvalidStateError" exception and terminate these steps.

  2. If the state is not DONE, return null and terminate these steps.

  3. If the error flag is set, return null and terminate these steps.

  4. Return the document response entity body.

The responseXML attribute has XML in its name for historical reasons. It also returns HTML resources as documents.

4.9 Events summary

This section is non-normative.

The following events are dispatched on XMLHttpRequest and/or XMLHttpRequestUpload objects:

Event name Interface Dispatched when…
readystatechange Event The readyState attribute changes at some seemingly arbitrary times for historical reasons.
loadstart ProgressEvent When the request starts.
progress ProgressEvent While sending and loading data.
abort ProgressEvent When the request has been aborted. For instance, by invoking the abort() method.
error ProgressEvent When the request has failed.
load ProgressEvent When the request has successfully completed.
timeout ProgressEvent When the author specified timeout has passed before the request could complete.
loadend ProgressEvent When the request has completed (either in success or failure).

5 Interface FormData

The FormData object represents an ordered collection of entries. Each entry has a name, a value, a type, and optionally a filename (if type is "file").

[Constructor,
 Constructor(HTMLFormElement form)]
interface FormData {
  void append(DOMString name, Blob value, optional DOMString filename);
  void append(DOMString name, DOMString value);
};

5.1 Constructors

fd = new FormData()

Returns a new FormData object.

The FormData() constructor must return a new FormData object.

The FormData(form) constructor must return a new FormData object with as entries the result of constructing the form data set for form.

5.2 The append() method

fd . append(name, value [, filename])

Appends a new name/value-pair to the FormData object, optionally with a filename.

The append(name, value, filename) method must create a new entry with the following parameters set and append it to the end of the collection the FormData object represents:

  • Set its name to name.
  • Set its value to value.
  • Set its type to "text" if value is a string and "file" if it is a Blob.
  • If its type is "file" set its filename to "blob".
  • If its type is "file" and value is a File whose name attribute is not the empty string, set entry's filename to the attribute's value.
  • If the filename parameter is not omitted set entry's filename to filename.

References

Normative references

[COOKIES]
HTTP State Management Mechanism, Adam Barth. IETF.
[CORS]
Cross-Origin Resource Sharing, Anne van Kesteren. W3C.
[DOM]
DOM4, Anne van Kesteren, Aryeh Gregor and Ms2ger. W3C.
[ECMASCRIPT]
ECMAScript Language Specification. ECMA.
[FILEAPI]
File API, Arun Ranganathan and Jonas Sicking. W3C.
[HTML]
HTML, Ian Hickson. WHATWG.
[HTTP]
Hypertext Transfer Protocol -- HTTP/1.1, Roy Fielding, James Gettys, Jeffrey Mogul et al.. IETF.
[HTTPAUTH]
HTTP Authentication: Basic and Digest Access Authentication, J. Franks, Phillip Hallam-Baker, J. Hostetler et al.. IETF.
[HTTPVERBSEC]
Multiple vendors' web servers enable HTTP TRACE method by default. US-CERT.
Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method. US-CERT.
HTTP proxy default configurations allow arbitrary TCP connections. US-CERT.
[PROGRESSEVENTS]
Progress Events, Anne van Kesteren. W3C.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, Scott Bradner. IETF.
[TYPEDARRAY]
Typed Array, David Herman and Kenneth Russell. Khronos.
[WEBIDL]
Web IDL, Cameron McCormack. W3C.
[XML]
Extensible Markup Language, Tim Bray, Jean Paoli, C. M. Sperberg-McQueen et al.. W3C.
[XMLNS]
Namespaces in XML, Tim Bray, Dave Hollander, Andrew Layman et al.. W3C.

Acknowledgments

The editor would like to thank Addison Phillips, Ahmed Kamel, Alex Hopmann, Alex Vincent, Alexey Proskuryakov, Asbjørn Ulsberg, Boris Zbarsky, Björn Höhrmann, Cameron McCormack, Chris Marrin, Christophe Jolif, Charles McCathieNevile, Dan Winship, David Andersson, David Flanagan, David Håsäther, David Levin, Dean Jackson, Denis Sureau, Doug Schepers, Douglas Livingstone, Elliotte Harold, Eric Lawrence, Eric Uhrhane, Erik Dahlström, Geoffrey Sneddon, Gideon Cohn, Gorm Haug Eriksen, Håkon Wium Lie, Hallvord R. M. Steen, Henri Sivonen, Huub Schaeks, Ian Davis, Ian Hickson, Ivan Herman, Jarred Nicholls, Jeff Walden, Jens Lindström, Jim Deegan, Jim Ley, Joe Farro, Jonas Sicking, Julian Reschke, 呂康豪 (Kang-Hao Lu), Karl Dubost, Lachlan Hunt, Maciej Stachowiak, Magnus Kristiansen, Marc Hadley, Marcos Caceres, Mark Baker, Mark Birbeck, Mark Nottingham, Mark S. Miller, Martin Hassman, Mohamed Zergaoui, Ms2ger, Odin Hørthe Omdal, Olli Pettay, Pawel Glowacki, Peter Michaux, Philip Taylor, Robin Berjon, Rune Halvorsen, Ruud Steltenpool, Sergiu Dumitriu, Sigbjørn Finne, Simon Pieters, Stewart Brodie, Sunava Dutta, Thomas Roessler, Tom Magliery, Yehuda Katz, and Zhenbin Xu for their contributions to this specification.

Special thanks to the Microsoft employees who first implemented the XMLHttpRequest interface, which was first widely deployed by the Windows Internet Explorer browser.

Special thanks also to the WHATWG for drafting an initial version of this specification in their Web Applications 1.0 document (now renamed to HTML). [HTML]

Thanks also to all those who have helped to improve this specification by sending suggestions and corrections. (Please, keep bugging us with your issues!)

'Language > JAVASCRIPT' 카테고리의 다른 글

마우스 커서 포지션 이동  (0) 2013.05.22
XMLHttpRequest 고급 기능  (1) 2013.04.29
XMLHttpRequest  (0) 2013.04.29
자바스크립트  (0) 2013.02.22
팝업창에 POST로 값넘기기  (0) 2012.11.22
:

XMLHttpRequest

Language/JAVASCRIPT 2013. 4. 29. 18:07

http://www.w3.org/TR/2012/NOTE-XMLHttpRequest1-20120117/#event-handler-attributes



Abstract

The XMLHttpRequest specification defines an API that provides scripted client functionality for transferring data between a client and a server.

Status of this Document

Beware. This specification was last published as a Candidate Recommendation, but it is no longer in active maintenance, contains known errors, and the Web Applications Working Group does not intend to maintain it further. See XMLHttpRequest for the Working Group's latest specification.

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This is the 17 January 2012 Working Group Note of XMLHttpRequest. Please send comments to public-webapps@w3.org (archived) with [XHR-NOTE] at the start of the subject line.

Publication as a W3C Working Group Note does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document is produced by the Web Applications (WebApps) Working Group. The WebApps Working Group is part of the Rich Web Clients Activity in the W3C Interaction Domain.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of Contents

1. Introduction

This section is non-normative.

The XMLHttpRequest object implements an interface exposed by a scripting engine that allows scripts to perform HTTP client functionality, such as submitting form data or loading data from a server. It is the ECMAScript HTTP API.

The name of the object is XMLHttpRequest for compatibility with the Web, though each component of this name is potentially misleading. First, the object supports any text based format, including XML. Second, it can be used to make requests over both HTTP and HTTPS (some implementations support protocols in addition to HTTP and HTTPS, but that functionality is not covered by this specification). Finally, it supports "requests" in a broad sense of the term as it pertains to HTTP; namely all activity involved with HTTP requests or responses for the defined HTTP methods.

Some simple code to do something with data from an XML document fetched over the network:

function test(data) {
 // taking care of data
}

function handler() {
 if(this.readyState == 4 && this.status == 200) {
  // so far so good
  if(this.responseXML != null && this.responseXML.getElementById('test').firstChild.data)
     // success!
   test(this.responseXML.getElementById('test').firstChild.data);
  else
   test(null);
 } else if (this.readyState == 4 && this.status != 200) {
  // fetched the wrong page or network error...
  test(null);
 }
}

var client = new XMLHttpRequest();
client.onreadystatechange = handler;
client.open("GET", "unicorn.xml");
client.send();

If you just want to log a message to the server:

function log(message) {
 var client = new XMLHttpRequest();
 client.open("POST", "/log");
 client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
 client.send(message);
}

Or if you want to check the status of a document on the server:

function fetchStatus(address) {
 var client = new XMLHttpRequest();
 client.onreadystatechange = function() {
  // in case of network errors this might not give reliable results
  if(this.readyState == 4)
   returnStatus(this.status);
 }
 client.open("HEAD", address);
 client.send();
}

2. Conformance Criteria

Everything in this specification is normative except for diagrams, examples, notes and sections marked non-normative.

The key words must, must not, should, should not, and may in this document are to be interpreted as described in RFC 2119. [RFC2119]

This specification defines the following classes of products:

Conforming user agent

A user agent must behave as described in this specification in order to be considered conformant.

If the user agent is not a conforming XML user agent the XML response entity body must (always) be null.

User agents may implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.

This specification uses both the terms "conforming user agent(s)" and "user agent(s)" to refer to this product class.

Conforming XML user agent

An XML user agent must be a conforming user agent and must be a conforming XML processor that reports violations of namespace well-formedness. [XML]

2.1. Dependencies

This specification relies on several underlying specifications.

DOM

A conforming user agent must support at least the subset of the functionality defined in DOM Events and DOM Core that this specification relies upon, such as various exceptions and EventTarget. [DOM2Events] [DOM3Core]

HTML5

A conforming user agent must support at least the subset of the functionality defined in HTML5 that this specification relies upon, such as the basics of the Window object and serializing a Document object. [HTML5]

The Window Object 1.0 draft is not referenced normatively as it appears to be no longer maintained and HTML5 defines the Window object in more detail. This specification already depends on HTML5 for other reasons so there is not much additional overhead because of this.

HTTP

A conforming user agent must support some version of the HTTP protocol. Requirements regarding HTTP are made throughout the specification. [RFC2616]

Web IDL

A conforming user agent must also be a conforming implementation of the IDL fragments in this specification, as described in the Web IDL specification. [WebIDL]

2.2. Terminology

Convert a DOMString to a sequence of Unicode characters is defined by the Web IDL specification. [WebIDL]

The term user credentials for the purposes of this specification means cookies, HTTP authentication, and client-side SSL certificates. Specifically it does not refer to proxy authentication or the Origin header. [COOKIES]

The terms and algorithms <fragment>, <scheme>, cookie-free Document object, document base URL, document's character encoding, event handler attributes, event handler event type, fetch, fully active, Function, innerHTML, origin, preferred MIME name, resolve a URL, same origin, storage mutex, task, task source, task queues, URL, URL character encoding, queue a task, and valid MIME type are defined by the HTML5 specification. [HTML5]

The term entity body is used as described in RFC 2616. Method token is used as described in section 5.1.1 of RFC 2616. field-name and field-value are used as described in section 4.2 of RFC 2616. [RFC2616]

To deflate a DOMString into a byte sequence means to create a sequence of bytes such that the nth byte of the sequence is equal to the low-order byte of the nth code point in the original DOMString.

To inflate a byte sequence into a DOMString means to create a DOMString such that the nth code point has 0x00 as the high-order byte and the nth byte of the byte sequence as the low-order byte.

userinfo is used as described in section 3.2.1 of RFC 3986. [RFC3986]

To dispatch a readystatechange event means that an event with the name readystatechange, which does not bubble and is not cancelable, and which uses the Event interface, is to be dispatched at the XMLHttpRequest object.

2.3. Extensibility

User agents, Working Groups, and other interested parties are strongly encouraged to discuss extensions on a relevant public forum, preferably public-webapps@w3.org. If this is for some reason not possible prefix the extension in some way and start the prefix with an uppercase letter. E.g. if company Foo wants to add a private method bar() it could be named FooBar() to prevent clashes with a potential future standardized bar().

3. The XMLHttpRequest Interface

The XMLHttpRequest object can be used by scripts to programmatically connect to their originating server via HTTP.

[NoInterfaceObject]
interface XMLHttpRequestEventTarget : EventTarget {
  // for future use
};

[Constructor]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // event handler attributes
           attribute Function onreadystatechange;

  // states
  const unsigned short UNSENT = 0;
  const unsigned short OPENED = 1;
  const unsigned short HEADERS_RECEIVED = 2;
  const unsigned short LOADING = 3;
  const unsigned short DONE = 4;
  readonly attribute unsigned short readyState;

  // request
  void open(DOMString method, DOMString url);
  void open(DOMString method, DOMString url, boolean async);
  void open(DOMString method, DOMString url, boolean async, DOMString? user);
  void open(DOMString method, DOMString url, boolean async, DOMString? user, DOMString? password);
  void setRequestHeader(DOMString header, DOMString value);
  void send();
  void send(Document data);
  void send([AllowAny] DOMString? data);
  void abort();

  // response
  readonly attribute unsigned short status;
  readonly attribute DOMString statusText;
  DOMString getResponseHeader(DOMString header);
  DOMString getAllResponseHeaders();
  readonly attribute DOMString responseText;
  readonly attribute Document responseXML;
};

3.1. Origin and Base URL

Each XMLHttpRequest object has an associated XMLHttpRequest origin and an XMLHttpRequest base URL.

This specification defines their values when the global object is represented by the Window object. When the XMLHttpRequest object is used in other contexts their values will have to be defined as appropriate for that context. That is considered to be out of scope for this specification.

In environments where the global object is represented by the Window object the XMLHttpRequest object has an associated XMLHttpRequest Document which is the Document object associated with the Window object for which the XMLHttpRequest interface object was created.

The XMLHttpRequest Document is used to determine the XMLHttpRequest origin and XMLHttpRequest base URL at a later stage.

3.2. Task Sources

The task source used by this specification is the XMLHttpRequest task source.

3.3. Constructors

client = new XMLHttpRequest()
Returns a new XMLHttpRequest object.

When the XMLHttpRequest() constructor is invoked, the user agent must return a new XMLHttpRequest object.

3.4. Event Handler Attributes

The following is the event handler attribute (and its corresponding event handler event type) that must be supported as DOM attribute by the XMLHttpRequest object:

event handler attribute event handler event type
onreadystatechange readystatechange

3.5. States

client . readyState

Returns the current state.

The XMLHttpRequest object can be in several states. The readyState attribute must return the current state, which must be one of the following values:

UNSENT (numeric value 0)

The object has been constructed.

OPENED (numeric value 1)

The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method.

HEADERS_RECEIVED (numeric value 2)

All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available.

LOADING (numeric value 3)

The response entity body is being received.

DONE (numeric value 4)

The data transfer has been completed or something went wrong during the transfer (e.g. infinite redirects).

The OPENED state has an associated send() flag that indicates whether the send() method has been invoked. It can be either true or false and has an initial value of false.

The DONE state has an associated error flag that indicates some type of network error or abortion. It can be either true or false and has an initial value of false.

3.6. Request

The XMLHttpRequest object holds the following request metadata variables:

The asynchronous flag
True when fetching is done asychronously. False when fetching is done synchronously.
The request method
The method used in the request.
The request URL
The URL used in the request.
The request username
The username used in the request or null if there is no username.
The request password
The password used in the request or null if there is no password.
The author request headers
A list consisting of HTTP header name/value pairs to be used in the request.
The request entity body
The entity body used in the request.

3.6.1. The open() method

client . open(method, url, async, user, password)

Sets the request method, request URL, asynchronous flag, request username, and request password.

Throws a SYNTAX_ERR exception if one of the following is true:

  • method is not a valid HTTP method.
  • url cannot be resolved.
  • url contains the "user:password" format in the userinfo production.

Throws a SECURITY_ERR exception if method is a case-insensitive match for CONNECT, TRACE or TRACK.

Throws a SECURITY_ERR exception if the origin of url does not match the XMLHttpRequest origin.

Throws a NOT_SUPPORTED_ERR exception if the <scheme> of url is not supported.

When the open(method, url, async, user, password) method is invoked, the user agent must run these steps (unless otherwise indicated):

  1. If the XMLHttpRequest object has an associated XMLHttpRequest Document run these substeps:

    1. If the XMLHttpRequest Document is not fully active raise an INVALID_STATE_ERR exception and terminate the overall set of steps.

    2. Let XMLHttpRequest base URL be the document base URL of the XMLHttpRequest Document.

    3. Let XMLHttpRequest origin be the origin of the XMLHttpRequest Document.

  2. If any code point in method is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating method it does not match the Method token production raise a SYNTAX_ERR exception and terminate these steps. Otherwise let method be the result of deflating method.

  3. If method is a case-insensitive match for CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE, or TRACK subtract 0x20 from each byte in the range 0x61 (ASCII a) to 0x7A (ASCII z).

    If it does not match any of the above, it is passed through literally, including in the final request.

  4. If method is a case-sensitive match for CONNECT, TRACE, or TRACK raise a SECURITY_ERR exception and terminate these steps.

    Allowing these methods poses a security risk. [HTTPVERBSEC]

  5. Let url be a URL.

  6. Let URL character encoding of url be UTF-8.

  7. Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error raise a SYNTAX_ERR exception and terminate these steps.

  8. Drop <fragment> from url.

  9. If url contains an unsupported <scheme> raise a NOT_SUPPORTED_ERR and terminate these steps.

  10. If the "user:password" format in the userinfo production is not supported for the relevant scheme and url contains this format raise a SYNTAX_ERR and terminate these steps.

  11. If url contains the "user:password" format let temp user be the user part and temp password be the password part.

  12. If url just contains the "user" format let temp user be the user part.

  13. If the origin of url is not same origin with the XMLHttpRequest origin raise a SECURITY_ERR exception and terminate these steps.

  14. Let async be the value of the async argument or true if it was omitted.

  15. If the user argument was not omitted follow these sub steps:

    1. If user is null let temp user be null.

    2. Otherwise let temp user be user.

    These steps override anything that may have been set by the url argument.

  16. If the password argument was not omitted follow these sub steps:

    1. If password is null let temp password be null.

    2. Otherwise let temp password be password.

    These steps override anything that may have been set by the url argument.

  17. Abort the send() algorithm.

  18. The user agent should cancel any network activity for which the object is responsible.

  19. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove those tasks.

  20. Set variables associated with the object as follows:

  21. Switch the the state to OPENED.

  22. Dispatch a readystatechange event.

3.6.2. The setRequestHeader() method

client . setRequestHeader(header, value)

Appends an header to the list of author request headers or if the header is already in the author request headers its value appended to.

Throws an INVALID_STATE_ERR exception if the state is not OPENED or if the send() flag is true.

Throws a SYNTAX_ERR exception if header is not a valid HTTP header field name or if value is not a valid HTTP header field value.

As indicated in the algorithm below certain headers cannot be set and are left up to the user agent. In addition there are certain other headers the user agent will take control of if they are not set by the author as indicated at the end of the send() method section.

When the setRequestHeader(header, value) method is invoked, the user agent must run these steps:

  1. If the state is not OPENED raise an INVALID_STATE_ERR exception and terminate these steps.

  2. If the send() flag is true raise an INVALID_STATE_ERR exception and terminate these steps.

  3. If any code point in header is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating header it does not match the field-name production raise a SYNTAX_ERR exception and terminate these steps. Otherwise let header be the result of deflating header.

  4. If any code point in value is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS or after deflating value it does not match the field-value production raise a SYNTAX_ERR exception and terminate these steps. Otherwise let value be the result of deflating value.

    The empty string is legal and represents the empty header value.

  5. Terminate these steps if header is a case-insensitive match for one of the following headers:

    • Accept-Charset
    • Accept-Encoding
    • Connection
    • Content-Length
    • Cookie
    • Cookie2
    • Content-Transfer-Encoding
    • Date
    • Expect
    • Host
    • Keep-Alive
    • Referer
    • TE
    • Trailer
    • Transfer-Encoding
    • Upgrade
    • User-Agent
    • Via

    … or if the start of header is a case-insensitive match for Proxy- or Sec- (including when header is just Proxy- or Sec-).

    The above headers are controlled by the user agent to let it control those aspects of transport. This guarantees data integrity to some extent. Header names starting with Sec- are not allowed to be set to allow new headers to be minted that are guaranteed not to come from XMLHttpRequest.

  6. If header is not in the author request headers list append header with its associated value to the list and terminate these steps.

  7. If header is in the author request headers list either use multiple headers, combine the values or use a combination of those (section 4.2, RFC 2616). [RFC2616]

See also the send() method regarding user agent header handling for caching, authentication, proxies, and cookies.

// The following script:
var client = new XMLHttpRequest();
client.open('GET', 'demo.cgi');
client.setRequestHeader('X-Test', 'one');
client.setRequestHeader('X-Test', 'two');
client.send();

// ...would result in the following header being sent:
...
X-Test: one, two
...

3.6.3. The send() method

client . send(data)

Initiates the request. The optional argument provides the request entity body. The argument is ignored if request method is GET or HEAD.

Throws an INVALID_STATE_ERR exception if the state is not OPENED or if the send() flag is true.

When the send(data) method is invoked, the user agent must run the following steps (unless otherwise noted). This algorithm gets aborted when the open() or abort() method is invoked. When the send() algorithm is aborted the user agent must terminate the algorithm after finishing the step it is on.

The send() algorithm can only be aborted when the asynchronous flag is true and only after the method call has returned.

  1. If the state is not OPENED raise an INVALID_STATE_ERR exception and terminate these steps.

  2. If the send() flag is true raise an INVALID_STATE_ERR exception and terminate these steps.

  3. If the request method is a case-sensitive match for GET or HEAD act as if data is null.

    If the data argument has been omitted or is null, do not include a request entity body and go to the next step.

    Otherwise, let encoding be null, mime type be null, and then follow these rules:

    If data is a Document

    Let encoding be the preferred MIME name of the character encoding of data. If encoding is UTF-16 change it to UTF-8.

    Let mime type be "application/xml;charset=" followed by encoding.

    Let the request entity body be the result of getting the innerHTML attribute on data converted to Unicode and encoded as encoding. Re-raise any exception this raises.

    In particular, if the document cannot be serialized an INVALID_STATE_ERR exception is raised.

    Subsequent changes to the Document have no effect on what is submitted.

    If data is a DOMString

    Let encoding be UTF-8.

    Let mime type be "text/plain;charset=UTF-8".

    Let the request entity body be data converted to Unicode and encoded as UTF-8.

    If a Content-Type header is set using setRequestHeader() whose value is a valid MIME type and has a charset parameter whose value is not a case-insensitive match for encoding, and encoding is not null, set all the charset parameters of the Content-Type header to encoding.

    If no Content-Type header has been set using setRequestHeader() and mime type is not null set a Content-Type request header with as value mime type.

  4. If the asynchronous flag is false release the storage mutex.

  5. Set the error flag to false.

  6. If the asynchronous flag is true run these substeps:

    1. Set the send() flag to true.

    2. Dispatch a readystatechange event.

      The state does not change. The event is dispatched for historical reasons.

    3. Return the send() method call, but continue running the steps in this algorithm.

  7. Fetch the request URL from origin XMLHttpRequest origin, with the synchronous flag set if the asynchronous flag is false, using HTTP method request method, user request username (if non-null) and password request password (if non-null), taking into account the request entity body, list of author request headers and the rules listed at the end of this section.

    If the asynchronous flag is false

    While making the request also follow the same-origin request event rules.

    The send() method call will now be returned by virtue of this algorithm ending.

    If the asynchronous flag is true

    Make progress notifications.

    Make upload progress notifications.

    While processing the request, as data becomes available and when the user interferes with the request, queue tasks to update the response entity body and follow the same-origin request event rules.


If the user agent allows the end user to configure a proxy it should modify the request appropriately; i.e., connect to the proxy host instead of the origin server, modify the Request-Line and send Proxy-Authorization headers as specified.


If the user agent supports HTTP Authentication and Authorization is not in the list of author request headers, it should consider requests originating from the XMLHttpRequest object to be part of the protection space that includes the accessed URIs and send Authorization headers and handle 401 Unauthorized requests appropriately.

If authentication fails, Authorization is not in the list of author request headers, request username is null, and request password is null, user agents should prompt the end user for their username and password.

If authentication fails, Authorization is not in the list of author request headers, request username is non-null, and request password is non-null, user agents must not prompt the end user for their username and password. [RFC2617]

End users are not prompted if username/password are provided through the open() API so that authors can implement their own user interface.


If the user agent supports HTTP State Management it should persist, discard and send cookies (as received in the Set-Cookie and Set-Cookie2 response headers, and sent in the Cookie header) as applicable. [COOKIES]


If the user agent implements a HTTP cache it should respect Cache-Control request headers set by the setRequestHeader() (e.g., Cache-Control: no-cache bypasses the cache). It must not send Cache-Control or Pragma request headers automatically unless the end user explicitly requests such behavior (e.g. by reloading the page).

For 304 Not Modified responses that are a result of a user agent generated conditional request the user agent must act as if the server gave a 200 OK response with the appropriate content. The user agent must allow setRequestHeader() to override automatic cache validation by setting request headers (e.g. If-None-Match or If-Modified-Since), in which case 304 Not Modified responses must be passed through. [RFC2616]


If the user agent implements server-driven content-negotiation it should set Accept-Encoding and Accept-Charset headers as appropriate. For Accept and Accept-Language the user agent must follow these constraints:

Responses must have the content-encodings automatically decoded. [RFC2616]


Besides the author request headers user agents should not include additional request headers other than those mentioned above or other than those authors are not allowed to set using setRequestHeader(). This ensures that authors have a reasonably predictable API.

3.6.4. Infrastructure for the send() method

The same-origin request event rules are as follows:

If the response has an HTTP status code of 301, 302, 303, or 307

If the origin of the URL conveyed by the Location header is same origin with the XMLHttpRequest origin and the redirect does not violate infinite loop precautions, transparently follow the redirect while observing the same-origin request event rules.

Otherwise, this is a network error.

HTTP places requirements on the user agent regarding the preservation of the request method and request entity body during redirects, and also requires end users to be notified of certain kinds of automatic redirections.

If the end user cancels the request

This is an abort error.

If there is a network error

In case of DNS errors, TLS negotiation failure, or other type of network errors, this is a network error. Do not request any kind of end user interaction.

This does not include HTTP responses that indicate some type of error, such as HTTP status code 410.

Once all HTTP headers have been received and the asynchronous flag is true (and this is not an HTTP redirect)

Switch to the HEADERS_RECEIVED state.

Once the first byte (or more) of the response entity body has been received and the asynchronous flag is true
If there is no response entity body and the asynchronous flag is true

Switch to the LOADING state.

Once the whole response entity body has been received
If there is no response entity body and the asynchronous flag is false or the state is LOADING

Switch to the DONE state.


When something is said to be a network error run the request error steps for exception NETWORK_ERR.

When something is said to be an abort error run the request error steps for exception ABORT_ERR.

When something is said to be a request error for exception exception run these steps:

  1. The user agent should cancel any network activity for which the object is responsible.

  2. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove those tasks.

  3. Set the response entity body to null.

  4. Empty the list of author request headers.

  5. Set the the error flag to true.

  6. Switch the state to DONE.

  7. If the asynchronous flag is false raise an exception exception and terminate the overall set of steps.

  8. Dispatch a readystatechange event.

    At this point it is clear that the asynchronous flag is true.

  9. Terminate the overall algorithm.

A future version of this specification will dispatch an error/abort event here as well. (Depending on the type of error.)


When it is said to switch to the HEADERS_RECEIVED state run these steps:

  1. Switch the state to HEADERS_RECEIVED.

  2. Dispatch a readystatechange event.

When it is said to switch to the LOADING state run these steps:

  1. Switch the state to LOADING.

  2. Dispatch a readystatechange event.

When it is said to switch to the DONE state run these steps:

  1. If the asynchronous flag is false update the response entity body.

  2. Switch the state to DONE.

  3. Dispatch a readystatechange event.

3.6.5. The abort() method

client . abort()
Cancels any network activity.

When the abort() method is invoked, the user agent must run these steps (unless otherwise noted):

  1. Abort the send() algorithm.

  2. The user agent should cancel any network activity for which the object is responsible.

  3. If there are any tasks from the object's XMLHttpRequest task source in one of the task queues, then remove those tasks.

  4. Set the response entity body to null.

  5. Empty the list of author request headers.

  6. Set the error flag to true.

  7. If the state is UNSENT, OPENED with the send() flag being false, or DONE go to the next step.

    Otherwise run these substeps:

    1. Switch the state to DONE.

    2. Set the send() flag to false.

    3. Dispatch a readystatechange event.

    A future version of this specification will dispatch an abort event here.

  8. Switch the state to UNSENT.

    No readystatechange event is dispatched.

3.7. Response

3.7.1. The status attribute

client . status

Returns the HTTP status code.

The status attribute must return the result of running these steps:

  1. If the state is UNSENT or OPENED return 0 and terminate these steps.

  2. If the error flag is true return 0 and terminate these steps.

  3. Return the HTTP status code.

3.7.2. The statusText attribute

client . statusText

Returns the HTTP status text.

The statusText attribute must return the result of running these steps:

  1. If the state is UNSENT or OPENED return the empty string and terminate these steps.

  2. If the error flag is true return the empty string and terminate these steps.

  3. Return the HTTP status text.

3.7.3. The getResponseHeader() method

client . getResponseHeader(header)

Returns the header field value from the response of which the field name matches header, unless the field name is Set-Cookie or Set-Cookie2.

When the getResponseHeader(header) is invoked, the user agent must run these steps:

  1. If the state is UNSENT or OPENED return null and terminate these steps.

  2. If the error flag is true return null and terminate these steps.

  3. If any code point in header is higher than U+00FF LATIN SMALL LETTER Y WITH DIAERESIS return null and terminate these steps.

  4. Let header be the result of deflating header.

  5. If header is a case-insensitive match for Set-Cookie or Set-Cookie2 return null and terminate these steps.

  6. If header is a case-insensitive match for multiple HTTP response headers, return the inflated values of these headers as a single concatenated string separated from each other by a U+002C COMMA U+0020 SPACE character pair and terminate these steps.

  7. If header is a case-insensitive match for a single HTTP response header, return the inflated value of that header and terminate these steps.

  8. Return null.

For the following script:

var client = new XMLHttpRequest();
client.open("GET", "unicorns-are-teh-awesome.txt", true);
client.send();
client.onreadystatechange = function() {
  if(this.readyState == 2) {
    print(client.getResponseHeader("Content-Type"));
  }
}

The print() function will get to process something like:

text/plain; charset=UTF-8

3.7.4. The getAllResponseHeaders() method

client . getAllResponseHeaders()

Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2.

When the getAllResponseHeaders() method is invoked, the user agent must run the following steps:

  1. If the state is UNSENT or OPENED return the empty string and terminate these steps.

  2. If the error flag is true return the empty string and terminate these steps.

  3. Return all the HTTP headers, excluding headers that are a case-insensitive match for Set-Cookie or Set-Cookie2, inflated, as a single string, with each header line separated by a U+000D CR U+000A LF pair, excluding the status line, and with each header name and header value separated by a U+003A COLON U+0020 SPACE pair.

For the following script:

var client = new XMLHttpRequest();
client.open("GET", "narwhals-too.txt", true);
client.send();
client.onreadystatechange = function() {
 if(this.readyState == 2) {
  print(this.getAllResponseHeaders());
 }
}

The print() function will get to process something like:

Date: Sun, 24 Oct 2004 04:58:38 GMT
Server: Apache/1.3.31 (Unix)
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/plain; charset=utf-8

3.7.5. Response Entity Body

The response MIME type is the MIME type the Content-Type header contains without any parameters or null if the header could not be parsed properly or was omitted. The override MIME type is always null. Final MIME type is the override MIME type unless that is null in which case it is the response MIME type.

The response charset is the value of the charset parameter of the Content-Type header or null if there was no charset parameter or if the header could not be parsed properly or was omitted. The override charset is always null. Final charset is the override charset unless that is null in which case it is the response charset.

Override MIME type and override charset are introduced here solely to make editing several levels of XMLHttpRequest simultaneously somewhat easier. Apologies for any confusion they might cause.


The response entity body is the fragment of the entity body of the response received so far (LOADING) or the complete entity body of the response (DONE). If the response does not have an entity body the response entity body is null.

The response entity body is updated as part of the send() algorithm.


The text response entity body is a DOMString representing the response entity body. The text response entity body is the return value of the following algorithm:

  1. If the response entity body is null return the empty string and terminate these steps.

  2. Let charset be the final charset.

  3. Let mime be the final MIME type.

  4. If charset is null and mime is null, text/xml, application/xml or ends in +xml use the rules set forth in the XML specifications to determine the character encoding. Let charset be the determined character encoding.

  5. If charset is null and mime is text/html follow the rules set forth in the HTML specification to determine the character encoding. Let charset be the determined character encoding. [HTML5]

  6. If charset is null then, for each of the rows in the following table, starting with the first one and going down, if the first bytes of bytes match the bytes given in the first column, then let charset be the encoding given in the cell in the second column of that row. If there is no match charset remains null.

    Bytes in Hexadecimal Description
    FE FF UTF-16BE BOM
    FF FE UTF-16LE BOM
    EF BB BF UTF-8 BOM
  7. If charset is null let charset be UTF-8.

  8. Return the result of decoding the response entity body using charset. Replace bytes or sequences of bytes that are not valid accordng to the charset with a single U+FFFD REPLACEMENT CHARACTER character.

Authors are strongly encouraged to encode their resources using UTF-8.


The document response entity body is either a Document representing the response entity body or null. The document response entity body is the return value of the following algorithm:

  1. If the response entity body is null terminate these steps and return null.

  2. If final MIME type is not null, text/xml, application/xml, and does not end in +xml terminate these steps and return null.

  3. Let document be a cookie-free Document object that represents the result of parsing the response entity body into a document tree following the rules from the XML specifications. If this fails (unsupported character encoding, namespace well-formedness error et cetera) terminate these steps return null. [XML]

    Scripts in the resulting document tree will not be executed, resources referenced will not be loaded and no associated XSLT will be applied.

  4. Return document.

3.7.6. The responseText attribute

client . responseText

Returns the text response entity body.

The responseText attribute must return the result of running these steps:

  1. If the state is not LOADING or DONE return the empty string and terminate these steps.

  2. Return the text response entity body.

3.7.7. The responseXML attribute

client . responseXML

Returns the document response entity body.

The responseXML attribute must return the result of running these steps:

  1. If the state is not DONE return null and terminate these steps.

  2. Return the document response entity body.

4. Exceptions

Several algorithms in this specification may result in an exception being thrown. These exceptions are all part of the group ExceptionCode and use the DOMException object, which is defined in DOM Level 3 Core. In addition this specification extends the ExceptionCode group with several new constants as indicated below. [DOM3Core]

Thus, exceptions used by this specification and not defined in this section are defined by DOM Level 3 Core.

const unsigned short SECURITY_ERR = 18;
const unsigned short NETWORK_ERR = 19;
const unsigned short ABORT_ERR = 20;

The SECURITY_ERR exception is raised if an attempt is made to perform an operation or access some data in a way that would be a security risk or a violation of the user agent's security policy.

The NETWORK_ERR exception is raised when a network error occurs in synchronous requests.

The ABORT_ERR exception is raised when the user aborts a request in synchronous requests.

These exceptions will be folded into an update of DOM Level 3 Core in due course, as they are appropriate for other API specifications as well.

References

Unless marked "Non-normative" these references are normative.

[COOKIES]
HTTP State Management Mechanism (work in progress), A. Barth. IETF.
[DOM2Events]
Document Object Model (DOM) Level 2 Events Specification, T. Pixley. W3C.
[DOM3Core]
Document Object Model (DOM) Level 3 Core Specification, A. Le Hors, P. Le Hégaret, L. Wood, G. Nicol, J. Robie, M. Champion, S. Byrne. W3C.
[ECMAScript]
ECMAScript Language Specification. ECMA.
[HTML5]
HTML5 (work in progress), I. Hickson. W3C.
HTML5 (work in progress), I. Hickson. WHATWG.
[HTTPVERBSEC]
(Non-normative) Multiple vendors' web servers enable HTTP TRACE method by default, US-CERT.
(Non-normative) Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method, US-CERT.
(Non-normative) HTTP proxy default configurations allow arbitrary TCP connections, US-CERT.
[RFC2046]
Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types, N. Freed, N. Borenstein. IETF.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF.
[RFC2616]
Hypertext Transfer Protocol -- HTTP/1.1, R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee. IETF.
[RFC2617]
HTTP Authentication: Basic and Digest Access Authentication, P. Hallam-Baker, J. Hostetler, S. Lawrence, P. Leach, A. Luotonen, L. Stewart. IETF.
[RFC3986]
Uniform Resource Identifier (URI): Generic Syntax, T. Berners-Lee, R. Fielding, L. Masinter. IETF.
[RFC3987]
Internationalized Resource Identifiers (IRIs), M. Duerst, M. Suignard. IETF.
[WebIDL]
Web IDL (work in progress), C. McCormack. W3C.
[XML]
Extensible Markup Language (XML) 1.0, T. Bray, J. Paoli, C. Sperberg-McQueen, E. Maler, F. Yergeau. W3C.
Namespaces in XML, T. Bray, D. Hollander, A. Layman, R. Tobin, H. S. Thompson. W3C.

Acknowledgments

The editor would like to thank Addison Phillips, Ahmed Kamel, Alex Hopmann, Alex Vincent, Alexey Proskuryakov, Asbjørn Ulsberg, Boris Zbarsky, Björn Höhrmann, Cameron McCormack, Christophe Jolif, Charles McCathieNevile, Dan Winship, David Andersson, David Håsäther, David Levin, Dean Jackson, Denis Sureau, Doug Schepers, Douglas Livingstone, Elliotte Harold, Eric Lawrence, Erik Dahlström, Geoffrey Sneddon, Gideon Cohn, Gorm Haug Eriksen, Håkon Wium Lie, Hallvord R. M. Steen, Huub Schaeks, Ian Davis, Ian Hickson, Ivan Herman, Jeff Walden, Jens Lindström, Jim Deegan, Jim Ley, Joe Farro, Jonas Sicking, Julian Reschke, Karl Dubost, Lachlan Hunt, Maciej Stachowiak, Magnus Kristiansen, Marc Hadley, Marcos Caceres, Mark Baker, Mark Birbeck, Mark Nottingham, Mark S. Miller, Martin Hassman, Mohamed Zergaoui, Olli Pettay, Pawel Glowacki, Peter Michaux, Philip Taylor, Robin Berjon, Rune Halvorsen, Ruud Steltenpool, Simon Pieters, Stewart Brodie, Sunava Dutta, Thomas Roessler, Tom Magliery, and Zhenbin Xu for their contributions to this specification.

Special thanks to the Microsoft employees who first implemented the XMLHttpRequest interface, which was first widely deployed by the Windows Internet Explorer browser.

Special thanks also to the WHATWG for drafting an initial version of this specification in their Web Applications 1.0 document (now renamed to HTML5). [HTML5]

Thanks also to all those who have helped to improve this specification by sending suggestions and corrections. (Please, keep bugging us with your issues!)

'Language > JAVASCRIPT' 카테고리의 다른 글

XMLHttpRequest 고급 기능  (1) 2013.04.29
XMLHttpRequest Level 2  (0) 2013.04.29
자바스크립트  (0) 2013.02.22
팝업창에 POST로 값넘기기  (0) 2012.11.22
자바스크립트 정규식  (0) 2012.01.04
: