zoukankan      html  css  js  c++  java
  • Javascript中怎么实现继承?

    传统的继承:

    var Person = function (name) {

        this.name = name || "default name";

        if (typeof Person._initialized == "undefined") {
            Person.prototype.getName = function () {
                return this.name;
            };
            Person._initialized = true;
        }
    };

    var Author = function (name, books) {
        Person.call(this, name);
        this.books = books || [];

        /*
        if (typeof Author._initialized == "undefined") {
            Author.prototype = new Person();
            Author.prototype.constructor = Author;
            Author.prototype.getBooks = function () {
                return this.books;
            };
            Author._initialized = true;
        }
        
    */
    };
    Author.prototype = new Person();
    Author.prototype.constructor = Author;
    Author.prototype.getBooks = function () {
        return this.books;
    };


    var p1 = new Person("zhangsan");
    var p2 = new Person("lisi");
    console.log(p1.getName());
    console.log(p2.getName());

    var a1 = new Author("Raymond", ["Pro Javascript Design Pattern", "Asp.net Framework"]);
    var a2 = new Author("Rock", ["Oracle & PL SQL"]);
    console.log(a1.getName());
    console.log(a1.getBooks());
    console.log(a2.getName());
    console.log(a2.getBooks());

    注意:注释的代码是我老喜欢用的动态原型。但是,很遗憾,它不能用在这里。因为,第一次调用Author构造函数执行到此处时,Author的实例对象已经被初始化了,改变Author的prototype已经不能对它形成影响(但是会对之后创建的Author对象实例起作用)。

          为了更加OOP,我们自己模拟一下extend关键字。具体如下:  

    var extend = function (subClass, superClass) {

        var F = function () { };
        F.prototype = superClass.prototype;
        subClass.prototype = new F();
        subClass.prototype.constructor = subClass;

        subClass.superClass = superClass.prototype;
        if (superClass.prototype.constructor != superClass) {
            superClass.prototype.constructor = superClass;
        }
    };

    var Person = function (name) {
        this.name = name || "default name";

        if (typeof Person._initialized == "undefined") {
            Person.prototype.getName = function () {
                return this.name;
            };
            Person._initialized = true;
        }
    };

    var Author = function (name, books) {
        Author.superClass.constructor.call(this, name);
        this.books = books || [];
    };
    extend(Author, Person);
    Author.prototype.getBooks = function () {
        return this.books;
    };

         还有一种被称为:prototypal的方式: 

    function clone(object) {

        function F() { }
        F.prototype = object;

        return new F();
    }

    var Person = {
        name: "default name",
        configure: function (name) {
            this.name = name;
        },
        getName: function () {
            return this.name;
        }
    };

    var Author = clone(Person);
    Author.books = [];
    Author.configure = function (name, books) {
        // Person.configure(name);
        this.name = name;
        this.books = books;
    };
    Author.getBooks = function () {
        return this.books;
    };

    这里对象类不再通过function实现,而是通过object literal。 因为没有构造器了,构造的实现迁移到configure方法中。遗憾的是,至今我仍没有找到合适的方法在Author类中override configure方法(被注释那一行),最后只能重复去赋值name。需要注意的是,这里author继承自Person的成员,在未被author重新创建(赋值)前,均通过prototype链指向的是对应于Person中的成员。虽然,书中提出用工厂方法来Person创建对象的成员,但我始终觉得它不是很合适,并且不能解决override的问题。

       最后一个就是Mixin了。如下: 

    function augment(receivingClass, givingClass, isOverideExsitingMember, requestMemberArray) {
        if (requestMemberArray) {
            for (key in requestMemberArray) {
                var memberKey = requestMemberArray[key];
                if (givingClass.prototype[memberKey] && (isOverideExsitingMember || !receivingClass.prototype[memberKey])) {
                    receivingClass.prototype[memberKey] = givingClass.prototype[memberKey];
                }
            }
        } else {
            for (memberKey in givingClass.prototype) {
                if (isOverideExsitingMember || !receivingClass.prototype[memberKey]) {
                    receivingClass.prototype[memberKey] = givingClass.prototype[memberKey];
                }
            }
        }
    }

    var Person = function (name) {
        this.name = name || "default name";
    };
    Person.prototype.getName = function () {
        return this.name;
    };

    var Mixin = function () { };
    Mixin.prototype = {
        serialize: function () {
            var output = [];
            for (key in this) {
                output.push(key + ':' + this[key]);
            };
            return output.join(',');
        },
        getName: function () {
            return "This is test method from Mixin.";
        }
    };

    augment(Person, Mixin, true);

    var p1 = new Person("zhangsan");
    var p2 = new Person("lisi");
    alert(p1.getName());
    console.log(p1.serialize());

    其实,我觉得它更多的是一种组合的概念,而不是继承。

         这里讲了继承的主干概念外,其实还涉及到了extend、clone、augment的模拟实现,可以将方法独立拿去使用。download

  • 相关阅读:
    Random简介
    十道海量数据处理面试题
    Django models 的字段类型
    执行monkey APK 制作
    MTK平台-抓取蓝牙log
    超级硬件代理解决企业Web提速上网问题
    Red Hat Linux 安装 (本地、网络安装)
    由安装两块网卡的linux系统中引起网络不通想到的
    Linux企业应用--RHAS 2.1 下安装中文 Lotus Domino R 6.5 图解
    巧用Linux 架设TFTP Server备份路由器的配置文件
  • 原文地址:https://www.cnblogs.com/Langzi127/p/2683624.html
Copyright © 2011-2022 走看看