一种基于JS原型链的类的构造与派生。原创

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一种基于JS原型链的类的构造与派生。原创相关的知识,希望对你有一定的参考价值。

转载请注明出处

2016.7.5 by Totooria Hyperion

http://demo.th-shr.com:9999/

 

// 初始化prototype和静态方法
function initClass(constructor,_proto) {
    // 配置prototype
    for(var key in _proto) {
        constructor.prototype[key] = _proto[key];
        if(typeof _proto[key] == "function") {
            Object.defineProperty(constructor.prototype,key,{"enumerable":false});
        }
    }
    // 为Class扩展方法/属性的函数
    constructor.extend = function(obj) {
        for(var key in obj) {
            if(this.hasOwnProperty(key)) {
                Error("this property already exist");
            } else {
                this.prototype[key] = obj[key];
                if(typeof obj[key] == "function") {
                    Object.defineProperty(this.prototype,key,{"enumerable":false});
                }
            }
        }
    }
    // 为Class删除方法/属性的函数
    constructor.delete = function(array) {
        array.forEach(function(item){
            delete this.prototype[item];
        });
    }
    // 为Class重写方法/属性的函数
    constructor.rewrite = function(key,value) {
        this.prototype[key] = value;
        if(typeof this.prototype[key] == "function") {
            Object.defineProperty(this.prototype,key,{"enumerable":false});
        }
    }
}

// 声明一个类,如果有基类superType,则生成其子类
function Class(name,constructor,_proto,superType){
    // 适配浏览器和非浏览器(nodejs等)
    var Global = Global || window;
    
    if(superType) {
    
        // 创建一个Class并进行初始化和父类初始化(组合继承:原型链继承+借用构造函数)
        Global[name] = function (obj) {
            var arg = obj ? obj : {};
            superType.call(this,arg);
            constructor.call(this,arg);
        };
        Global[name].name = name;
        Object.defineProperty(Global[name],"name",{"value":name,"enumerable":false,"writable":false});
        
        // 寄生继承
        var pro = Object.create(superType.prototype);
        pro["constructor"] = Global[name];
        Global[name].prototype = pro;
        // 使构造函数不可被for-in遍历,排除干扰
        Object.defineProperty(Global[name].prototype,"constructor",{"enumerable":false});
        
        // 初始化prototype和静态方法
        initClass(Global[name],_proto);
    
    } else {
        
        // 创建一个Class
        Global[name] = constructor;
        Object.defineProperty(Global[name],"name",{"value":name,"enumerable":false,"writable":false});

        // 初始化prototype和静态方法
        initClass(Global[name],_proto);
    }
}

 

测试代码如下:

Class("Person",function (obj){
    obj.name ? this.name = obj.name : obj.name ;
},{
    "name":"Unnamed",
    "gender":"Male",
    "sayHello":function(){
        console.log(this.name + ":Hello");
    }
});

Class("PersonWithAge",function(obj){
    obj.age ? this.age = obj.age : obj.age;
},{
    "age":"1",
    "sayGoodbye":function(){
        console.log(this.name + ":Goodbye");
    }
},Person);

Class("PersonMaria",function(obj){
    // obj.age ? this.age = obj.age : obj.age;
},{
    "name":"Maria",
    "sayGoodbye":function(){
        console.log(this.name + ":Goodbye");
    }
},Person);

Class("PersonMariaWithAge",function(obj){
    obj.age ? this.age = obj.age : obj.age;
},{
    "name":"Maria",
    "age":"1",
    "sayGoodbye":function(){
        console.log(this.name + ":Goodbye");
    }
},Person);

var jack = new Person({"name":"Jack"});

var potterWithAge = new PersonWithAge({"name":"Potter","age":"18"});

var maria = new PersonMaria();

var mariaWithAge = new PersonMariaWithAge({"age":"16"});

console.log(jack);
//console.log(jack.constructor);
console.log(jack instanceof Person);
console.log(potterWithAge);
//console.log(potterWithAge.constructor);
console.log(potterWithAge instanceof Person);
console.log(potterWithAge instanceof PersonWithAge);
console.log(maria);
//console.log(maria.constructor);
console.log(maria instanceof Person);
console.log(maria instanceof PersonMaria);
console.log(mariaWithAge);
//console.log(mariaWithAge.constructor);
console.log(mariaWithAge instanceof Person);
console.log(mariaWithAge instanceof PersonMariaWithAge);

Class("PersonWithAgeAndHeight",function(obj){
    obj.height ? this.height = obj.height : obj.height;
},{
    "height":"180",
    "sayHeight":function(){
        console.log(this.name + ":Height is " + this.height);
    }
},PersonWithAge);

var johnWithAgeAndHeight = new PersonWithAgeAndHeight({"name":"John","height":"160"});

console.log(johnWithAgeAndHeight);
console.log(johnWithAgeAndHeight instanceof Person);
console.log(johnWithAgeAndHeight instanceof PersonWithAge);
console.log(johnWithAgeAndHeight instanceof PersonWithAgeAndHeight);

function getInfo(obj){var str = "<br>{<br>";for(key in obj) {str += "&nbsp;&nbsp;" + key + ‘:"‘ + obj[key] + ‘",<br>‘};str.slice(0,-5);str+="}";return str;}

document.write(getInfo(jack) + "<br>");
//console.log(jack.constructor);
document.write("jack instanceof Person&nbsp;:&nbsp;" + (jack instanceof Person) + "<br>");
document.write(getInfo(potterWithAge) + "<br>");
//console.log(potterWithAge.constructor);
document.write("potterWithAge instanceof Person&nbsp;:&nbsp;" + (potterWithAge instanceof Person) + "<br>");
document.write("potterWithAge instanceof PersonWithAge&nbsp;:&nbsp;" + (potterWithAge instanceof PersonWithAge) + "<br>");
document.write(getInfo(maria) + "<br>");
//console.log(maria.constructor);
document.write("maria instanceof Person&nbsp;:&nbsp;" + (maria instanceof Person) + "<br>");
document.write("maria instanceof PersonMaria&nbsp;:&nbsp;" + (maria instanceof PersonMaria) + "<br>");
document.write(getInfo(mariaWithAge) + "<br>");
//console.log(mariaWithAge.constructor);
document.write("mariaWithAge instanceof Person&nbsp;:&nbsp;" + (mariaWithAge instanceof Person) + "<br>");
document.write("mariaWithAge instanceof PersonMariaWithAge&nbsp;:&nbsp;" + (mariaWithAge instanceof PersonMariaWithAge) + "<br>");
document.write(getInfo(johnWithAgeAndHeight) + "<br>");
document.write("johnWithAgeAndHeight instanceof Person&nbsp;:&nbsp;" + (johnWithAgeAndHeight instanceof Person) + "<br>");
document.write("johnWithAgeAndHeight instanceof PersonWithAge&nbsp;:&nbsp;" + (johnWithAgeAndHeight instanceof PersonWithAge) + "<br>");
document.write("johnWithAgeAndHeight instanceof PersonWithAgeAndHeight&nbsp;:&nbsp;" + (johnWithAgeAndHeight instanceof PersonWithAgeAndHeight) + "<br>");
document.write("johnWithAgeAndHeight instanceof PersonMaria&nbsp;:&nbsp;" + (johnWithAgeAndHeight instanceof PersonMaria) + "<br>");

 

测试结果如下(浏览器窗口输出):

{
  name:"Jack",
  gender:"Male",
}
jack instanceof Person : true

{
  name:"Potter",
  age:"18",
  gender:"Male",
}
potterWithAge instanceof Person : true
potterWithAge instanceof PersonWithAge : true

{
  name:"Maria",
  gender:"Male",
}
maria instanceof Person : true
maria instanceof PersonMaria : true

{
  age:"16",
  name:"Maria",
  gender:"Male",
}
mariaWithAge instanceof Person : true
mariaWithAge instanceof PersonMariaWithAge : true

{
  name:"John",
  height:"160",
  age:"1",
  gender:"Male",
}
johnWithAgeAndHeight instanceof Person : true
johnWithAgeAndHeight instanceof PersonWithAge : true
johnWithAgeAndHeight instanceof PersonWithAgeAndHeight : true
johnWithAgeAndHeight instanceof PersonMaria : false

 

以上是关于一种基于JS原型链的类的构造与派生。原创的主要内容,如果未能解决你的问题,请参考以下文章

js中原型,原型链的学习与认识

理解js中是原型链? 如何实现继承?

JS中原型链的理解

js 继承与原型链

JS中原型链的理解

js原型链和继承的理解