黑铁时代
Programing is not only one kind of technology, but also one kind of art.

JavaScript的面向对象主要是基于原型进行实现,传统的写法在开发中很不方便,于是创建一个工厂类,用于创建“类”。

/**
* Clone the attribute
* @param attribute
*/

执行深拷贝,主要是针对那些属于对象类型的属性,进行克隆

var cloneAttribute = function( attribute ) {

switch( Object.prototype.toString.call( attribute ) ) {

// Null
case '[object Null]':
  return null;
break;
// Array
case '[object Array]':
  return attribute.slice( 0 );
break;
// String or Number
case '[object String]':
case '[object Number]':
  return attribute.toString();
break;
// Object
case '[object Object]':
  // Null
  if ( attribute === null ) {
    return null;
  }
  // Element node
  else if ( attribute.nodeType === 1 ) {
    return document.createElement( attribute.nodeName );
  }
  // Others
  else {
    return attribute;
  }
break;
// Others
default:
  return attribute;
break;
}
}

/**
* The factory to create class
* @param name The class name
* @param extend The super class that will be inherited
* @param implement The interfaces that will be implemented
* @param property All the attributes and functions that will be used to create new class
*/

name 类名

extend:继承的父类,function对象

implement:继承的接口,类似{ name:123 }的对象

property:新创建的类的属性和方法,也是类似json格式的对象

主要原理是用闭包的方式保存属性attributes,方法放在原型上面。如果需要继承父类,实例化一个空对象,空对象的原型用于放置父类的原型,将这个空对象作为类的原型,就可以实现继承了。静态变量直接写在类上面,就可以继承了。不支持多继承,支持多接口集成,implement可以为存放多个接口对象的数组。实现了在子类中访问超类的同名方法,即被子类重写的方法,用_parent访问。所有_开头的属性和方法都是私有的,这只是一种人为的约束,技术上目前无法约束。_init是默认的构造函数。

shark.classFactory = function( name, extend, implement, property ) {
  var attributes = {}, // To store all the attributes for new class
  prototype = {}; // The prototype of new class

  // The parent class prototype
  var parentPrototype = {};

  // If the extend param is defined, means new class will inherited from the extend param
  if ( typeof extend === 'function' ) {
    var F = function(){};
    parentPrototype = F.prototype = extend.prototype;
    prototype = new F();
  }

  // Push the implement and property together
  var _tmpArr = [];
  if ( implement ) {
    if ( !Array.isArray( implement ) ) {
        _tmpArr.push( implement );
    }
    else {
      _tmpArr = implement;
    }
  }
  if ( property ) {
    _tmpArr.push( property );
  }

  // Deal with the interfaces and property
  for ( var i = 0, len = _tmpArr.length; i < len; i++ ) {
    var _interface = _tmpArr[ i ];
    for( var index in _interface ) {
      prop = _interface[ index ];

    // Function
    if ( typeof prop === 'function' ) {
      prototype[ index ] = !parentPrototype[ index ] ? prop : ( function() {
        var _parentFunction = parentPrototype[ index ],
        _ownerFunction = prop;

        return function() {
          this._parent = _parentFunction;
          _ownerFunction.apply( this, arguments );
          delete this._parent;
        }
      } )();
    }
    // Attribute
    else {
      attributes[ index ] = prop;
    }
  }
}

// Create class
function Class( flag ) {
  // Init the inherited attributes
  if ( typeof extend === 'function' ) {
    extend.call( this, false );
  }

  // Init the owner attributes
  for ( var index in attributes ) {
    this[ index ] = cloneAttribute( attributes[ index ] );
  }

  this.className = name;

  // Call the constructor
  if ( flag !== false && this._init ) {
    this._init.apply( this, arguments );
  }
}
Class.prototype = prototype;

// Inherit the static property
var hasOwnProp = Object.prototype.hasOwnProperty;
for ( var index in extend ) {
  if ( hasOwnProp.call( extend, index ) ) {
    Class[ index ] = extend[ index ];
  }
}

return Class;
}

 

用法:

父类: Person

var Person = shark.classFactory( 'Person', null, {
  name: 'leo',
  age: 20,
  _init: function( name ) {
    this.name = name;
  },
  setName: function( name ) {
    this.name = name;
  },
  getName: function() {
    return this.name;
  }
} );
var p1 = new Person(  'jack'  );
console.log( p1 );

子类:Student

var Student = shark.Class( 'Student', Person, {
  score: 100,
  _init: function( name, age, score ) {
    this._parent( name );
    this.age = age;

    this.score = score;
  },
  setScore: function( score ) {
    this.score = score;
  },
  getScore: function() {
    return score;
  },
  getName: function() {
    return 'Hello, you name is ' + this.name;
  },
} );
var s1 = new Student(  'shark', 15, 34 );

console.log( s1 );

 

缺点:不能通过对象的constructor进行对象识别,因为所有对象的constructor都是Object()

posted on 2012-09-23 23:25  黑铁时代  阅读(366)  评论(0编辑  收藏  举报