Rev. 2.73

prototype.js해독의 절정의 하나입니다.
Enumerable 클래스, 라고 표현하고 있습니다만, 이것 자체의인스턴스는 작성될 것은 없습니다.(원래, function는 아니기 때문에 작성할 수 없습니다만) 이 클래스는 다른 열거 가능한 클래스·오브젝트(Array, Hash, ObjectRange,Ajax.Responders, Element.ClassNames)에 의해 계승되는 것으로 실장됩니다.Java로 말하는 추상 클래스와 같은 것입니다. Ruby언어를 참고로 하고 있는 것 같습니다만, 필자는 Ruby를 모르기 때문에 그대로 해독합니다^^;

each 메서드
메서드_each에 무명 내부함수를 건네주고 있습니다.메서드_each는, Enumerable 클래스를 계승하는 클래스·오브젝트측에서 실장할 필요가 있습니다(추상 메서드 취급).

무명 함수의 주된 처리는,인수로 건네받은 함수(iterator)를 실행할 뿐입니다.value는 열거 가능한 오브젝트(this)의 각 요소의 값이 됩니다.이것은_each 메서드내에서 무명 함수에게 건네집니다.index는 실행마다 인크리먼트(increment) 됩니다.

무 명 함수는, 함수 iterator내에서의 에러를 catch 해, 에러 오브젝트가 전술$continue 오브젝트이면 무시, 그렇지 않으면 throw 합니다.더욱 each 메서드가_each 메서드의 에러를 catch 해, 에러 오브젝트가 전술$break 오브젝트이면 무시, 그렇지 않으면 throw 합니다.

var array = ["zero", "one", "two", "three"];
array.each(function(value, index){
  alert(index + ":" + value);
}); 
//"0:zero", "1:one", "2:two", "3:three"가 차례로 표시된다.

each 메서드는 이후의 Enumerable 클래스의 메서드로 이용되고 있습니다.

내부 함수(크로쟈)의 스코프의 특성
인수로서 건네받은 내부 함수(크로쟈)는, 원의 메서드의 변수(index)를 사용할 수가 있습니다.전술 「Function 클래스에 대한 확장(1)」로 기술한 「반환된 함수가 반환원함수의 변수를 사용할 수 있다」와 같은 도리입니다.자세하게는 그 쪽을 참조해 주세요. $breake오브젝트, $continue 오브젝트 다음의 Enumerable 클래스에서 에러 오브젝트로서 사용합니다.

all 메서드
전술 each 메서드를, 무명 내부함수를인수로 해 호출하고 있습니다.

무명 내부 함수는 인수의 함수(iterator)를, 요소의 값과 인덱스(을)를 인수로 해 호출합니다.iterator가 무지정 또는 null의 경우는, 전술 Prototype.K 메서드(을)를 호출하고 있습니다.!!(***)(은)는,***이 null(undefined) 또는 false이면 false, 그 이외이면 true가 됩니다.이것과 result와의 논리적을 result에 격납해, result가 false라면 그 시점에서 전술$break 에러오브젝트를throw 합니다.

each 메서드 실행 종료후, result를 반환합니다.

var array = ["zero", "one", null, "three"];
var ret = array.all(function(value, index){
  alert(index + ":" + value);
  return value;
});
//"0:zero", "1:one", "2:null"까지 표시된다. 
alert(ret);//"false"가 표시된다.

배열의 제3 요소 null가"two"라면 모두 표시되어 최후도 true가 됩니다.

throw 된$break 에러 오브젝트는 each 메서드의 두 개의 catch절을 양방 대로.둘째의 catch절로 조건 일치해 무시됩니다.이 동작에 관해서는 전술 each 메서드의 마지막【참고】로 확인해 보세요.(설명 방폐라고도 말하는><; 미안합니다···.)

any 메서드
전술 all 메서드와 구조는 거의 똑같습니다.차이는 iterator(또는 Prototype.K)의 결과가, null(undefined) 또는 false가 아닌 경우에$break를 throw 하는 것입니다.

var array = [null, false, "two", null];
var ret = array.any(function(value, index){
  alert(index + ":" + value);
  return value;
});
//"0:null", "1:false", "2:two"까지 표시된다. 
alert(ret);//"true"가 표시된다.

배열의"two"도 null나 false라면 모두 표시되어 최후도"false"라고 표시됩니다. 이후,reject메서드까지 기본 구조는 똑같습니다.그것까지는 간단한 설명과 예의 보고 기술합니다.

collect 메서드
iterator의 결과를 result에 push 메서드로 추가해 나가, 이것을 반환합니다.

var array = ["zero", "one", "two", "three"];
var ret = array.collect(function(value, index){
  return index + ":" + value;
});
alert(ret);
//ret는 배열."0:zero, 1:one, 2:two, 3:three"가 표시된다.

detect 메서드
iterator가 true를 반환한 시점에서 break($break를 throw) 해, 그 때의 요소의 값을 반환합니다.

var array = ["zero", "one", "two", "three"];
var ret = array.detect(function(value, index){
  return (value.length == 3); //length가 3의 경우 true를 반환
});
alert(ret);
//"one"가 표시된다.

findAll 메서드
iterator가 true를 반환했을 경우, 그 때의 요소의 값 모든 것을 배열에 격납해 반환합니다.

var array = ["zero", "one", "two", "three"];
var ret = array.findAll(function(value, index){
  return (value.length == 3); //length가 3의 경우 true를 반환
});
alert(ret);
//ret는 배열."one, two"가 표시된다.

grep메서드
제일 인수 pattern는정규 표현 오브젝트입니다.요소의 값을 toString로 캐릭터 라인화해, pattern에 성냥 했을 경우만, iterator로 처리한 결과를 배열 result에 격납해 반환합니다.iterator가 지정 없음의 경우는 Prototype.K 메서드로 값을 그대로 취급합니다.

var array = ["zero", "one", "two", "three"];
var ret = array.grep(/.*o$/, //최후가"o"의 캐릭터 라인에 성냥
function(value, index){
  return value.toString().toUpperCase(); //대문자로 해 반환
});
alert(ret);
//ret는 배열."ZERO, TWO"가 표시된다.

include 메서드
인수는 임의의 오브젝트 object만입니다.요소의 값이 object와 같은 오브젝트였던 경우, 그 시점에서 break($break를 throw) 합니다.발견되었을 경우는 true, 발견되지 않았던 경우는 false를 반환합니다.

var object0 = new Object();
var object1 = new Array();
var object2 = new String();
var object3 = new RegExp();
var object4 = new Object();
var array = [object0, object1, object2, object3];
alert(array.include(object0)); //true라고 표시된다
alert(array.include(object4)); //false라고 표시된다

inject 메서드
제일인수 memo를 초기치로서iterator에 의해 memo를 변경해 나가, 최종적으로 이것을 반환하고 있습니다.memo는 배열이나 커스텀오브젝트의 외, 캐릭터 라인이나 수치도 설정할 수 있습니다.

var array = ["one", "two", "three"];
var ret = array.inject(["zero"],
function(memo, value, index){
  memo.push(value);
  memo.push(value);
  return memo;
});
alert(ret);
//ret는 배열."zero, one, one, two, two, three, three"라고 표시된다.

invoke 메서드
전술 collect 메서드가 사용되고 있습니다.collect 메서드는 this의 각 요소의 값을 인수의함수로 처리해, 그 결과를 배열에 정리해 돌려주는 것입니다.collect 메서드에의 인수의 함수는, 각 요소의 값(이 경우 오브젝트)의 제일 인수 method와 동명의 메서드를 실행합니다.apply 함수에 의해 invoke의 제2 인수 이후를, value[method]의 인수로 하고 있습니다.

var dog = {
  sing : function(f, b){return f + "왕 " + b;}
}
var cat = {
  sing : function(f, b){return f + "―" + b;}
}
var cock = {
  sing : function(f, b){return f + "이끼 국고―" + b;}
}
var array = [dog, cat, cock];
var ret = array.invoke("sing", " 「", "」");
alert(ret);
//ret는 배열." 「왕」, 「―」, 「이끼 국고―」"라고 표시된다.

max 메서드
iterator의 처리 결과의 값이, 지금까지의 최대치 result보다 큰 경우에, result와 옮겨놓고 있습니다.결과적으로 최대치가 반환됩니다.iterator가 null(undefined)의 경우는, 제일 인수를 그대로 반환하는 Prototype.K 메서드가 사용됩니다.「value >= (result || value)」는, result의 초기치가 미정도리(undefined)이므로, 루프의 첫회로 반드시 true가 됩니다.

var array = ["zero", "one", "two", "three"];
var ret = array.max(function(value, index){
  return value.length - index;
});
alert(ret);
//"4"라고 표시된다."zero"의 문자수-0의 결과.

min 메서드
전술 max 메서드의 역이군요.

var array = ["zero", "one", "two", "three"];
var ret = array.min(function(value, index){
  return value.length - index;
});
alert(ret);
//"1"라고 표시된다."two"의 문자수-2의 결과.

pluck 메서드
각 요소의 값(이 경우 오브젝트)에 대해, 인수 property와 동명의 프롭퍼티를 배열에 격납해 반환하고 있습니다.

var array = ["zero", "one", "two", "three"];
var ret = array.pluck("length");
alert(ret);
//ret는 배열."4, 3,3,5"가 표시된다.

reject메서드
iterator가 false를 반환했을 경우, 그 때의 요소의 값 모든 것을 배열에 격납해 반환합니다.전술 findAll 메서드와 역의 기능입니다.

var array = ["zero", "one", "two", "three"];
var ret = array.reject(function(value, index){
  return (value.length == 3); //length가 3의 경우 true를 반환
});
alert(ret);
//ret는 배열."zero, three"가 표시된다.

sortBy 메서드
우선, 각 요소의 값을 value, iterator의 처리 결과를 criteria라는 이름의 프롭퍼티로 가지는, 오브젝트의 배열을 작성합니다.다음에, 이것을 기존의 sort 메서드로소트 하고 있습니다.소트는 각 오브젝트의 criteria 프롭퍼티를 바탕으로 실시합니다. 소트 함수는1이상정수를 반환하면(자) 서로 이웃이 되는 요소가 바뀌기 때문에, 이 경우, 승순 소트가 됩니다.마지막에 전술 pluck 메서드를 사용해, value 프롭퍼티만을 배열에 격납해 반환하고 있습니다.

var array = ["zero", "one", "two", "three"];
var ret = array.sortBy(function(value, index){
  return value.length;
});
alert(ret);
//ret는 배열."one, two, zero, three"가 표시된다.

즉 이것은 오브젝트 배열이 특정의 프롭퍼티로 소트 할 수 있다고 하는 것입니다.

이하는 2 차원 배열의 소트예입니다.

var array = [[0, 10], [1, 9], [2, 8], [3, 7]];
var ret = array.sortBy(function(value, index){
  return value[1];//2 번째로 소트
});
alert(Object.inspect(ret));
//"[[3, 7], [2, 8], [1, 9], [0, 10]]"라고 표시된다.

이하는 Hash 오브젝트(연상 배열)의 소트예입니다.반환되는 것은 키와 값이 대가 되어 있는 2 차원 배열이므로, 재차 Hash로 변환할 필요가 있습니다.(어쩐지···)

var hash = $H({'one':'1', 'two':'02', 'three':'003'});
var ret = hash.sortBy(function(prop, index){
  return prop.key;
}).inject($H(), function(memo, value, index){
  memo[value[0]] = value[1];
  return memo;
});
alert(Object.inspect(ret));
//"#<Hash:{'one': '1', 'three': '003', 'two': '02'}>"라고 표시된다.

prop.key를 prop.value로 하면 값에서의 소트가 됩니다.또, Number(prop.value) 그렇다면 수치로서 소트 합니다.-(Number(prop.value)) 그렇다면 수치로서 내림차순 소트가 됩니다.문자 사전순서의 내림차순은 간단하게는 쓸 수 없는 것 같습니다.(sortBy 후에 reverse 해 Hash로 할 수 밖에 없는 것 같은···)

toArray 메서드
각 요소의 값을 배열에 격납해 반환합니다.Array 클래스에서는 그다지 의미가 없습니다만,후술의 Hash 오브젝트를 Array 오브젝트로 변환하는 경우에 유효합니다. Array에서도, 오브젝트의 복제를 작성하는데 유효합니다.

var hash = $H({zero:"영", one:"일", two:"이", three:"참"});
var array = hash.toArray();
alert(array[2][0]); //"two"라고 표시된다
alert(array[2][1]); //"이"라고 표시된다
alert(array.two);//"undefined"라고 표시된다

zip메서드
last 메서드는 후술 「Array 클래스에의 확장」으로 추가되는 메서드입니다.배열의 마지막 요소를 반환합니다.인수의 최후가함수이면 기존pop메서드로 취득해iterator로 하고 있습니다.그렇지 않으면 Prototype.K를 iterator로 합니다.

다음에 요소가 자오브젝트만 의 배열([this])에, 기존 concat 메서드로 인수를 결합합니다.map 메서드는 전술 collect 메서드의 별명입니다(후술).이것과$A함수에 의해, 요소 모든 것을 Array 오브젝트로 변환해 collections에 격납하고 있습니다.

그리고는 collections의 각 요소에 대해, 같은 인덱스의 값을 전술 pluck 메서드로 꺼내, 이것을 iterator로 처리합니다.자오브젝트의 요소 몇분 이것을 반복해, 결과의 배열을 반환합니다. ···하지만, 여기서버그가 있습니다.이것이라면 iterator의 처리가 반영되지 않습니다.버젼 1.5.0_rc0에서는 수정되고 있는 것 같습니다.

var array = ["zero", "one", "two", "three"];
var ret = array.zip([0, 1, 2, 3], ["영", "일", "이", "참"],
function(value){ //v1.4.0에서는 무효
  return value.map(function(value2){return " 「" + value2 + "」"});
});
alert(ret[2]);
//ret[2]는 배열."two, 2, 이"라고 표시된다.
//v1.5.0_rc0 라면 " 「two」, 「2」, 「이」"라고 표시된다.

inspect 메서드
this를 전술 toArray 메서드로 Array 오브젝트로 변환해, Array 클래스의 inspect 메서드를 호출하고 있습니다.Array 클래스의 inspect 메서드는, 배열을 「[]」으로 묶어, 각 요소를 「,」그리고 단락지은 캐릭터 라인을 반환합니다.Array 클래스와 Hash 클래스는 inspect 메서드를 오버라이드(override) 하고 있기 때문에, 그 이외의 클래스·오브젝트로 이용됩니다.

직접 사용되는 것이 아니라, Object.inspect 메서드 경유의 이용을 상정하고 있는 것 같습니다.

var objR = $R(0, 5, true);
alert(Object.inspect(objR));
//"#<Enumerable:[0, 1, 2, 3, 4]>"라고 표시된다.

각각, 메서드의 별명을 정의하고 있습니다.Enumerable오브젝트에map, find, select, member, entries 메서드를 가지는 무명 오브젝트를 계승시키고 있습니다.

Comments

Got something to add? You can just leave a comment.

Your Reaction Time!

captcha

avatar