1.6.0 - 해당되는 글 1건

얼마전에 PrototypeJS가 1.6.0_rc0 버전이 공개되었습니다.
홈페이지에 공개된 내용은 간략하게 되어있어 어떤면이 변했는지 감으로만 알 수 있을뿐, 직접 코딩해보지 않으면 알 수 없는 법이므로 어떻게 달라졌는지 알아보도록 하겠습니다.

var Prototype = {
  Version: '1.6.0_rc0',
  Browser: {
    IE:     !!(window.attachEvent && !window.opera),
    Opera:  !!window.opera,
    WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
    Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
    MobileSafari: !!navigator.userAgent.match(/iPhone.*Mobile.*Safari/)
  },
 ...........
}

if (Prototype.Browser.MobileSafari)
  Prototype.BrowserFeatures.SpecificElementExtensions = false;



우선 처음부분에서 달라진건 역시 버전이군요 ^^; 그리고 밑에 보면 모바일사파리라고 해서 아이폰에 대비한 모습도 보이는군요. 이제는 모바일 디바이스도 지원해야하는 세상이네요..ㅎㅎ 허나 제가 아이폰이 없는관계로 테스트는 --;; 못하겠습니다.

그다음에 크게 바뀐 것중 하나가 Class 쪽입니다.
기존에는 단순하게
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}
이와 같은 형태였으나, 지금은 확 바뀌었군요. Class 관련 전체 코드는 아래와 같습니다.

var Class = {
  create: function(parent, methods) {
    if (arguments.length == 1 && !Object.isFunction(parent))
      methods = parent, parent = null;

    var method = function() {
      if (!Class.extending) this.initialize.apply(this, arguments);
    };

    method.superclass = parent;
    method.subclasses = [];

    if (Object.isFunction(parent)) {
      Class.extending = true;
      method.prototype = new parent();

      parent.subclasses.push(method);

      delete Class.extending;
    }

    if (methods) Class.extend(method, methods);
    method.prototype.constructor = method;

    return method;
  },

  extend: function(destination, source) {
    for (var name in source) Class.inherit(destination, source, name);
    return destination;
  },

  inherit: function(destination, source, name) {
    var prototype = destination.prototype, ancestor = prototype[name],
     descendant = source[name];
    if (ancestor && Object.isFunction(descendant) &&
        descendant.argumentNames().first() == "$super") {
      var method = descendant, descendant = ancestor.wrap(method);
      Object.extend(descendant, {
        valueOf:  function() { return method },
        toString: function() { return method.toString() }
      });
    }

    prototype[name] = descendant;

    if (destination.subclasses && destination.subclasses.length > 0) {
      for (var i = 0, subclass; subclass = destination.subclasses[i]; i++) {
        Class.extending = true;
        Object.extend(subclass.prototype, new destination());
        subclass.prototype.constructor = subclass;
        delete Class.extending;
        Class.inherit(subclass, destination.prototype, name);
      }
    }
  },

  mixin: function(destination, source) {
    return Object.extend(destination, source);
  }
};

무척이나 많이 바뀌었네요. 여기서 소스를 하나하나 뜯는것 보다, 바로 써먹을 수 있는것에 초점을 두겠습니다.
PJS 사이트에 예제가 하나 나와있긴하나 미완성 예제(제생각에 ^^)라 판단되어 조금 덧붙여봤습니다.
<script>
var Animal = Class.create({  
 initialize: function(name) {    
  this.name = name;  
 },  
 eat: function() {    
  return this.say("Yum!");  
 },  
 say: function(message) {   
  return this.name + ": " + message;  
 }
});

// subclass that augments a method
var Cat = Class.create(Animal, {  
 eat: function($super, food) {    
  if (food instanceof Mouse) return $super();    
  else return this.say("Yuk! I only eat mice.");  
  }
});

var Mouse = Class.create(Animal, {});
var Dog = Class.create(Animal,{})

var tom = new Cat('Toml');
var jerry = new Mouse('Jerry');
var goopy = new Dog('Goopy');

alert(tom.eat(jerry));
alert(tom.eat(goopy));

</script>

실행결과는 ? 그렇습니다. 첫번째 alert에는 Yum!, 다음 alert에는 Yuk! I only eat mice 라고 나옵니다.
여기서 중요한건 무엇일까요? 바로 메소드 오버라이드(override)가 가능하다는 것입니다. 오버라이드가 기본적으로 가능하려면,
클래스사이의 관계 즉, 수퍼클래스와 서브클래스의 개념을 지원해야 가능하다는 것이지요. 기존 1.5.1에서 클래스 상속이라고 했던것들은 모두 기존 메소드들의 대체였다면, 이번 버전에서의 상속은 같은 이름의 메소드가 있을경우 오버라이드 시키고 있습니다. PJS가 좀더 OOP에 한발짝 다가섰군요.

해당 소스의 자세한 분석은 다음에 하기로 하고 계속 되는 포스트에는 사용법에 맞춰 작성될것입니다.
요즘 하는일이 하도 많아서 언제쯤 분석하고 올릴 수 있을지 모르겠지만 ^^; 언젠가는 하겠죠? ㅎㅎ

posted by blankus

태그 - ,
Tip  |  2007/08/18 20:38