Javascript学习笔记9——prototype封装继承

上文中,我利用prototype的原理做了一个封装的New,然后我就想到,我是否可以用prototype的原理进一步封装面向对象的一些基本特征呢?比如继承。

好,那就让我们一步步打造,首先让我们来看下继承原本的写法:

    <script>
        var Person = function(name, age) {
            this.name = name;
            this.age = age;
        }
        Person.prototype.SayHello = function () {
            alert(this.name + "," + this.age);
        };
        var Programmer = function (name, age, salary) {
            Person.call(this, name, age);
            this.salary = salary;
        };
        Programmer.prototype = new Person();
        var pro = new Programmer("kym", 21, 500);
        pro.SayHello();
    </script>

我们看到,在实际上,继承的根本就在于这一步Programmer.prototype=new Person()。也就是说把Person加到原型链上。这一点在Javascript学习笔记7——原型链的原理 已经有过比较详尽的解释。

那也就是说,我们实现的关键就在于原型链的打造。

在上文中,我们用JSON来打造了一个原型,其原型链是p.__proto__=Person。那么我们希望在这个上封装继承,那么原型链应该是p.__proto__.__proto__=SuperClass,也就是说Person.__proto__=SuperClass。但是按照我们上面代码的继承方法,原型链关系是Person.__proto__=SuperClass.prototype。

这个和我们在上文中一样,我们的办法就是借助一个辅助函数,将原来的函数内的属性赋给X,然后令X.prototype=SuperClass即可,也就是说我们将子原型进行一个封装。

好,就按照这个思路,我们来实现利用原型链的继承关系的封装。

    <script>
        var Factory = {
            Create: function (className, params) {
                var temp = function () {
                    className.Create.apply(this, params);
                };
                temp.prototype = className;
                var result = new temp();
                return result;
            },

            CreateBaseClass: function (baseClass, subClass) {
                var temp = function () {
                    for (var member in subClass) {
                        this[member] = subClass[member];
                    }
                };
                temp.prototype = baseClass;
                return new temp();
            }
        };
        var People = {
            Create: function (name, age) {
                this.name = name;
                this.age = age;
            },
            SayHello: function () {
                alert("Hello,My name is " + this.name + ".I am " + this.age);
            }
        };
        var Temp = {
            Create: function (name, age, salary) {
                People.Create.call(this, name, age);
                this.salary = salary;
            },
            Introduce: function () {
                alert(this.name + "$" + this.age + "$" + this.salary);
            }
        };
        var Programmer = Factory.CreateBaseClass(People, Temp);
        var pro = Factory.Create(Programmer, ["kym", 21, 500]);
        pro.SayHello();
    </script>

 

这样就完成了我们对继承关系的封装。当然,我们也可以不单独写一个变量:

var Programmer = Factory.CreateBaseClass(People, 
{
    Create: function (name, age, salary) {
        People.Create.call(this, name, age);
        this.salary = salary;
    },
    Introduce: function () {
        alert(this.name + "$" + this.age + "$" + this.salary);
    }
});

当然,这全凭个人爱好了,个人认为第一种办法相对更清晰一些,但是第二种办法则更优雅。

退出

posted @   飞林沙  阅读(1562)  评论(4编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
点击右上角即可分享
微信分享提示