一种基于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
时间: 2024-10-11 03:11:40

一种基于JS原型链的类的构造与派生。【原创】的相关文章

JS 原型链图形详解

JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语言,是通过对象来交互的.即使ECMAScript里边也有基本类型,但是,当需要的时候,它们也会被转换成对象. 一个对象就是一个属性集合,并拥有一个独立的prototype(原型)对象.这个prototype可以是一个对象或者null.* 让我们看一个关于对象的基本例子.一个对象的prototype是

js原型链与继承(初体验)

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

浅谈js原型链与继承

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

js 原型链和继承(转)

在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var obj = { name: "obj" }; 我们通过控制台把 obj 打印出来: 我们会发现 obj 已经有几个属性(方法)了.那么问题来了:valueOf / toString / constructor 是怎么来?我们并没有给 obj.valueOf 赋值呀. 上面这个图有点难懂,我手画

简单粗暴地理解js原型链--js面向对象编程

简单粗暴地理解js原型链--js面向对象编程 原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧,想点与代码无关的事,比如人.妖以及人妖. 1)人是人他妈生的,妖是妖他妈生的.人和妖都是对象实例,而人他妈和妖他妈就是原型.原型也是对象,叫原型对象. 2)人他妈和人他爸啪啪啪能生出一堆人宝宝.妖他妈和妖他爸啪啪啪能生出一堆妖宝宝,啪啪啪就是构造函数,俗

深入理解JS原型链与继承

我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天要讨论的主题,有许多人写过许多精彩的文章,但是今天我还是想把自己的理解的知识记录下来.我在学习 掌握JS原型链和继承的时候,就是看得@阮一峰老师的写的文章,觉得他写的技术类的文章都容易让理解,简明概要,又好理解.他是我学习JS路程里面一个比较佩服的导师,昨天重新看了他写的<Javascript 面向

js原型链的深度理解!

一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object .Function 是 JS 自带的函数对象.下面举例说明 var o1 = {}; var o2 =new Object(); var o3 = new f1(); function f1(){}; var f2 = function(){}; var f3 = new Function('str','console.log(str)'); console.log(type

JS原型链

JS每个对象都有一个内部属性[[prototype]],我们通常称之为原型.原型的值可以是一个对象,也可以是null.如果它的值是一个对象,则这个对象也一定有自己的原型.这样就形成了一条线性的链,我们称之为原型链. 访问一个对象的原型可以使用ES5中的Object.getPrototypeOf方法,或者ES6中的__proto__属性. 原型链的作用是用来实现继承,比如我们新建一个数组,数组的方法就是从数组的原型上继承而来的. 在JavaScript中,每个函数 都有一个prototype属性,

JS原型链与几种继承方法的对比

继承的方式有两种:接口继承.实现继承接口继承:即虚函数,父类只定义接口,不具体实现子类继承接口,自己负责实现这个方法,运行时动态决定调用哪个实现.实现继承:父类实现的方法,子类可以直接调用 JS中只支持实现继承,以原型链来实现. 回顾一下构造函数.原型.实例的关系:每个构造函数都有一个原型对象,原型对象又都包含一个constructor指针指向构造函数,实例包含一个_proto_内部属性指向原型对象. 继承的实现方法(父类型叫Parent,子类型叫Child)原本Child.prototype