ECMAScriptweb前端开发必知之一:JS继承和后续基础总结

  首先,推荐一首博客豪情的博客JS提高:
http://www.cnblogs.com/jikey/p/3604459.html ,里面的链接全是精华,
一般人自莫晓他;

  我们见面先行从JS的着力的设计模式开始,由浅入深,
会描述prototype,__proto__,consturctor等基础知识和JS的周边继承方式
以及四个类工厂的引进和运用(包括JS.Class,prototype的类工厂,john
resig写的一个简洁类工厂仓库,以及Pjs一个不胜洒脱的继承库,很飘逸-_-),最后来3独参考资料链接:ECMAScript 1,最后出自我个人的视频,欢迎拍砖哇,
 ///(o)_(o)////。

  厂子模式:因为以用一个接口创建很多目标见面生大量之还代码,为了缓解者问题,人们就开始使用工厂模式:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        //工厂模式:因为使用用一个接口创建很多对象会产生大量的重复代码,为了解决这个问题,人们就开始使用工厂模式:
        function Person(hairs,face, eye) {
            var o = new Object();
            o.hairs = hairs;
            o.face = face;
            o.eye = eye;
            o.say = function(){
                console.log("say someting to me!");
            };
            return o;
        };
        //我们通过 Person(0,1,2)就可以创建一个包含特定信息的Person对象, 以后要生成对象直接执行Person然后给他传参数就好了;
        //比如我们要生成10个Person, 很方便很快;
        var c = 10;
        while( c-- ) {
            console.log(Person(c,c,c))
        };
    </script>
</body>
</html>

  


 

  构造函数模式:使用构造函数模式咱会少几再多代码,比如面的工厂模式咱俩可改写成: 

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        function Person(hairs, face, eye) {
            this.hairs = hairs;
            this.face = face;
            this.eye = eye;
        };
        //同样, 我们再生成10个小朋友
        var c = 10;
        while( c-- ) {
            console.log( new Person(c,c,c) );
        };

    </script>
</body>
</html>

 

  //知识点1: 那么工厂模式和构造函数模式产生什么区别吧:

  /*
  * 没有显式地创建对象
  * 直接拿性能和措施赋值给了this
  * 没有return语句
  * 构造函数的眼前有一个new;
  * */

*  // 知识点2:*

  /*
  * 通过new的构造函数会经四独号:
  * 1:创建一个初目标;
  * 2:把this赋值给此新对象
  * 3:执行构造函数中之代码
  * 4:返回新对象
  * */

 


 

  原型是神马? 原型就是是公用的主意还是性质,这么明白最简便, 当然:

      1、prototype本质上要一个JavaScript对象;

      2、每个函数都发出一个默认的prototype属性;

      3、通过prototype我们可以扩展Javascript的内建对象

  一些代码来明白原型的真面目:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        function Memo() {};
        Memo.prototype.hehe = 1;
        Memo.prototype.shut = function() {
            console.log("miaomiao")
        };
        var m0 = new Memo();
        var m1 = new Memo();
        console.log(m0.shut === m1.shut); //ture, 因为m0的shut和m1的shut就是指向了Memo.prototype.shut这个方法,所以他们相等;
        //Object.getPrototypeOf会返回实例的原型;
        console.log(Object.getPrototypeOf(m0)) //输出了:Memo {hehe: 1, shut: function}
        console.log( Memo.prototype.isPrototypeOf(m0) )// 输出: true;

        //原型对象有一个很大的问题要非常注意 ==》》 原型的属性和方法是被共享的, 比如:
        Memo.prototype.shut = "W_W";
        l(m0.shut) //输出:W_W, 悲剧了吧, 本来原型上的shut是个方法, 被改成字符串以后, 实例上的shut也发生了改变;
        l(m1.shut) //输出:W_W;

        m0.__proto__.shut = 1111; //m0的__proto__指向了Memo.prototype.shut,__proto__在标准浏览器下面是不能枚举到的,但确实是存在的一个属性;
        l(m1.shut) //输出了1111
        //只要原型上的属性或者方法被改了, 实例上的也会发生改变;
    </script>

</body>

</html>

 

  知识点:Object.getPrototypeOf;

      Fn.prototype.isPrototypeOf( instance );

 


  好的, 现在重新来询问一下constructor,
如果你都清楚constructor凡是什么的语,
 这段略过, constructor是默认指向创建当前目标的构造函数,
但是当时中有一对坑要顾, 比如你的原型prototype被反了,
实例的constructor就变换了 ,

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        var Fn = function(){
            //我是构造函数Fn;
        };
        l("Fn的constructor");
        l(Fn.prototype.constructor);
        /*输出function (){
         //我是构造函数Fn;
         } */

        var f = new Fn;
        l("f的constructor");
        l(f.constructor);
        /*输出;
         * function (){
         //我是构造函数Fn;
         }*/
        //当函数创建的时候默认就为prototype新建一个constructor指向自己;

        l(Fn.constructor === Function); //输出true, Function这个构造函数是Function;
        l(Fn.constructor) // 输出function Function() { [native code] } ,意思是Function这个构造函数 ;
        l(Fn.constructor === Fn.__proto__.constructor) //输出true; Fn的constructor实际上是指向Fn.__proto__的;

        //好的, 现在重新定义一个Fn;
        var Fn = function(){
            //我是构造函数Fn;
        };
        Fn.prototype = {};
        l(Fn.prototype.constructor)
        /*打印出了内部的代码, 为什么呢? 因为我们改变了Fn的原型, Fn的constructor指向了{}空对象的Contructor;
         * function Object() { [native code] }  */
    </script>
</body>
</html>

 

  大家自然要是懂的凡实例上之__proto__就是指向原型上之prototype
这样会掉走有弯路,可以节省又多的时用来拘禁片, 你明白的;
  每一个函数新建的时还出一个默认的prototype,
 prototype这个目标方面默认有一个对准自己的constructor;
  prototype和__proto__的区别:__proto__大凡实例和Person.prototype中的关联,而constructor是实例和Person之间的涉

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        var Fn = function() {};
        Fn.prototype.hehe = 1;
        Fn.prototype.lala = 2;
        var f = new Fn;
        l(f) //输出了Fn {hehe: 1, lala: 2} ;
        l(f.__proto__) //输出了Fn {hehe: 1, lala: 2} ;
        l(Fn.prototype === f.__proto__) //输出了true, 这里要懂的东西是实例上的__proto__这个属性指向了构造函数的prototype;
        l(f === f.__proto__) //输出false; 这里要懂的是f是new出来的实例;

        //因为f上面的hehe和lala都是继承的属性, 所以这里面的log并没有被输出;
        for(var p in f){
            l("输出所以属性:" + p); //输出所以属性:hehe demo.html:11;   输出所以属性:lala
            //过滤非私有属性;
            if( f.hasOwnProperty(p) )
                l("输出私有属性" + p); //因为f没有私有属性,所以这边没有log出来;
        };
    </script>
</body>
</html>

  

  有了点的基本功,
我们初步说说JS的面向对象和后续吧;

  1:做使用构造器和原型模式
这种模式是构造函数和原型混合的模式, 使用最广,
认同度也高的一律栽模式, 也是极致基础的模式;

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        function Duck( name ,word) {
            this.name = name;
            this.word = word;
        };
        Duck.prototype.say = function() {
            console.log( this.name+" say : " + this.word )
        };
        var duck = new Duck("nono","hehe");
        duck.say();
    </script>
</body>
</html>

 

   寄生组织模式; 听名字真个挺玄乎..其实跟工厂模式一模一样的,
其实就是由定义模型的包装;

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        function Foxy(name , word) {
            var result = new Object();
            result.name = name;
            result.word = word;
            return result;
        };
        l( new Foxy("nono","say someting") ); //输出:Object {name: "nono", word: "say someting"} ;
        function Monkey( ) {
            var aResult = [];
            //技巧:通过apply把arguments保存到数组;
            aResult.push.apply(aResult, arguments);
            return aResult;
        };
        l( new Monkey("nono","dino","kite","sam") );  //打印出了这个:["nono", "dino", "kite", "sam"];
        //要注意的是使用寄生模式的返回的对象和构造函数一点关系都没有;
    </script>
</body>
</html>

 

  JS的原型继承
继承是依赖让原型链的;那么JS原型链凡什么呢:
  /* 这段话慢慢读, 从搞基程序设计三抄过来的,很重要,
实体书最好团结看无异拘留哇;
  * ECMAScript中描述了原型链的定义, 并将原本型链作为落实持续的要方法,
基本思维是应用引用类型继承另一个援类型的性与章程。
  *
简单回顾一下构造函数,原型和实例的关系:每一个函数都来一个原型对象,
每一个原型对象还出一个针对构造函数的指针,
  * 而实例包含了一个针对性原型对象的里(不可见的)指针。
那么我们为原型对象等另一个档的实例, 那么这原型对象将会晤蕴藏对
  *
另一个原型对象的指针,如果其他一个原型对象又是赖为了别的原型的一个实例,
这样少见嵌套, 就形成了原型链;
  * */
  那么我们利用原型的原型链相互继承来写一个中坚的例子:  

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        var Fn = function() {
            this.property = true;
        }
        Fn.prototype.getFnProperty = function() {
            console.log( this.property );
        };
        var SubFn = function() {
            this.subProperty = false;
        };
        //SubFn继承了Fn的实例
        SubFn.prototype = new Fn();
        //为实例添加额外的实例方法;
        SubFn.prototype.getSubProperty = function(){
            console.log(this.subProperty);
        };
        var subFn = new SubFn();
        subFn.getFnProperty(); //输出了true
        subFn.getSubProperty(); //输出了false
        /*现在subFn的constructor 是
         function () {
         this.property = true;
         };
         所以要修正SubFn.prototype.constructor = SubFn
         */
    </script>
</body>
</html>

 

  原型式继承第二单例:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        // 首先, 准备一个方法;
        var inherit = function(o) {
            if(!typeof o === "object")return;
            function F () {}
            F.prototype = o;
            F.prototype.constructor = F;
            return new F();
        };

        var Fn = function() {
            this.property = true;
        }
        Fn.prototype.getFnProperty = function() {
            console.log( this.property );
        };
        var SubFn = function() {
            this.subProperty = false;
        };
        //SubFn继承了Fn的实例
        SubFn.prototype = new Fn();
        //为实例添加额外的实例方法;
        SubFn.prototype.getSubProperty = function(){
            console.log(this.subProperty);
        };
        var subFn = new SubFn();

        //这个方法的内部, 临时创建了一个构造函数, 然后将传入的对象作为这个构造函数的原型, 最后返回一个临时的新实例;
        //ECMASscript 5 有新增了一个Object.create 效果和inherit一模一样, 它可以接收第二个参数,
        // 第二个参数要通过defineProperties的方式设置,会覆盖原型的属性, 比如:
        Object.create(subFn, {
            getFnProperty: {
                value:1
            }
        });
        var Fn = function() {};
        //如果我们inherit传对象;
        Fn.prototype = inherit( {0:0,1:1,2:2,3:3,4:4} );
        l( new Fn ) //==>Fn {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, constructor: function(){....} 继承了哦
        //如果我们给inherit传一个构造函数的实例;
        Fn.prototype = inherit( new SubFn );
        l(new Fn);
    </script>
</body>
</html>

  有时候看到原型的各种引用会尿失禁, 引来引去的,坑爹啊,
不说了失去洗裤子了….

  ECMAScript 2

  

  寄生组合式继承  

  组合继承是JS的常用继承模式, 但是吧发出好的供不应求,
组合继承最老之题材的甭管什么状态下, 都见面简单赖调整用超类的构造函数;
  一个是在开创子类原型的时节, 另一个凡当子类构造函数的内部,
 那么子类的原型会包含有超类实例的满贯性质
  寄生组合式继承就是为解决子类原型包含有超类实例全部性能是题目而在的;
  

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        //最好所有的代码自己打一遍, 增加印象;
        function l ( arg ) {
            console.log( arg );
        };
    </script>

    <script>
        var inherit = function(o) {
            if(!typeof o === "object")return;
            function F () {}
            F.prototype = o;
            F.prototype.constructor = F;
            return new F();
        };
        //首先要准备inheritPrototype方法;
        var util = util || {};
        util.inherit = inherit;
        util.inheritPrototype = function(subType, superType) {
            var _prototype = this.inherit( superType.prototype );
            _prototype.constructor = subType;
            subType.prototype = _prototype;
        };
        function F( name ) {
            this.name = name;
            this.type = "human";
            this.habits = ["dance","code"];
        };
        F.prototype.laugh = function() {
            console.log("heha!");
        };
        var InheritF = function() {
            F.apply( this, arguments );
        };
        util.inheritPrototype(InheritF, F);
        InheritF.prototype.letsGo = function() {
            l("1,2,3,4")
        };
        var nono = new InheritF("nono");
        nono.habits.push("read books");
        l(nono.habits)
        var nonono = new InheritF("nono");
        l( nonono.habits );
        //继承的方法千万种,万变不离其宗;
    </script>
</body>
</html>

 

  JS各种以了继承库的类库推荐, 可以强化印象:

  首先, JS.Class 是一个mootools式的类工厂 基于
lunereaper<![[dawid.kraczkowski[at]gmail[dot]com]]>的档次进展修改,
让子类的贯彻再精简;

ECMAScript 3ECMAScript 4

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        JS = {};
        // 这个是库的源代码;
        JS.Class = function(classDefinition) {

            //返回目标类的真正构造器
            function getClassBase() {
                return function() {
                    //它在里面执行用户传入的构造器construct
                    //preventJSBaseConstructorCall是为了防止在createClassDefinition辅助方法中执行父类的construct
                    if (typeof this['construct'] === 'function' && preventJSBaseConstructorCall === false) {
                        this.construct.apply(this, arguments);
                    }
                };
            }
            //为目标类添加类成员与原型成员
            function createClassDefinition(classDefinition) {
                //此对象用于保存父类的同名方法
                var parent = this.prototype["parent"] || (this.prototype["parent"] = {});
                for (var prop in classDefinition) {
                    if (prop === 'statics') {
                        for (var sprop in classDefinition.statics) {
                            this[sprop] = classDefinition.statics[sprop];
                        }
                    } else {
                        //为目标类添加原型成员,如果是函数,那么检测它还没有同名的超类方法,如果有
                        if (typeof this.prototype[prop] === 'function') {
                            var parentMethod = this.prototype[prop];
                            parent[prop] = parentMethod;
                        }
                        this.prototype[prop] = classDefinition[prop];
                    }
                }
            }

            //其实就是这样的Base = function() {};别想太多了;
            var preventJSBaseConstructorCall = true;
            var Base = getClassBase();
            preventJSBaseConstructorCall = false;

            createClassDefinition.call(Base, classDefinition);

            //用于创建当前类的子类
            Base.extend = function(classDefinition) {

                //其实就是这样的Base = function() {};别想太多了;
                preventJSBaseConstructorCall = true;
                var SonClass = getClassBase();
                SonClass.prototype = new this();//将一个父类的实例当作子类的原型
                preventJSBaseConstructorCall = false;

                createClassDefinition.call(SonClass, classDefinition);
                SonClass.extend = this.extend;

                return SonClass;
            };
            return Base;
        };
    </script>
    <script>
        //这是实际案例;
        var Animal = JS.Class({
            construct: function(name) {
                this.name = name;
            },
            shout: function(s) {
                console.log(s);
            }
        });
        var animal = new Animal();
        animal.shout('animal'); // animal

        var Dog = Animal.extend({
            construct: function(name, age) {
                //调用父类构造器
                this.parent.construct.apply(this, arguments);
                this.age = age;
            },
            run: function(s) {
                console.log(s);
            }
        });
        var dog = new Dog("dog", 4);
        console.log(dog.name);
        dog.shout("dog"); // dog
        dog.run("run"); // run
        console.log(dog.constructor + "")
        var Shepherd = Dog.extend({
            statics: {//静态成员
                TYPE: "Shepherd"
            },
            run: function() {//方法链,调用超类同名方法
                this.parent.run.call(this, "fast");
            }
        });
        console.log(Shepherd.TYPE);//Shepherd
        var shepherd = new Shepherd("shepherd", 5);
        shepherd.run();//fast
        var a = new Animal("xx");
        console.log(a.run);
    </script>
    </body>
</html>

View Code

 

    prototype这个( ▼-▼ )库以前牛逼着为, 但是一百年河东一百年河西,
prototype当前的版是行版本的1.7平静版,prototype里面的接近工厂创建的主代码为吃我单独裁出来了,
源码也大都, 源码有我加的诠释,自己个人方便阅读,
HTML代码的结尾好写的几栽 创办类工厂的点子, 可以借鉴(我未曾看api,
源码就是api….)

ECMAScript 5ECMAScript 6

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>prototype Demo</title>
</head>
<body>
<script>
    var Class = (function() {

        var IS_DONTENUM_BUGGY = (function(){
            for (var p in { toString: 1 }) {
                if (p === 'toString') return false;
            }
            return true;
        })();

        Object.keys = Object.keys || (function() {
            if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
            var results = [];
            for (var property in object) {
                if (object.hasOwnProperty(property)) {
                    results.push(property);
                }
            }
            return results;
        })();
        Object.isFunction = function(fn) {
            return typeof fn === "function";
        };
        function argumentNames() {
            var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
                .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
                .replace(/\s+/g, '').split(',');
            return names.length == 1 && !names[0] ? [] : names;
        };
        function $A(iterable) {
            if (!iterable) return [];
            if ('toArray' in Object(iterable)) return iterable.toArray();
            var length = iterable.length || 0, results = new Array(length);
            while (length--) results[length] = iterable[length];
            return results;
        };

        function update(array, args) {
            var arrayLength = array.length, length = args.length;
            while (length--) array[arrayLength + length] = args[length];
            return array;
        };
                    //wrapper表示的是现在的方法;
        function wrap(wrapper) {
            //this指向的返回的闭包;
            var __method = this;
            return function() {
                        //a是指把orginalFu和当前的参数混合成一个数组;
                var a = update([__method.bind(this)], arguments);
                return wrapper.apply(this, a);
            };
        };

        Object.extend = extend;
        Function.prototype.argumentNames = argumentNames;
        Function.prototype.wrap = wrap;
        //把第二个参数的属性继承到第一个参数上;
        function extend(destination, source) {
            for (var property in source)
                destination[property] = source[property];
            return destination;
        };

        function subclass() {};
        function create() {
                               //相当于对参数进行slice;
            var parent = null, properties = $A(arguments);
            //如果第一个是函数就把这个函数作为超类;
            if (Object.isFunction(properties[0]))
                parent = properties.shift();

            //这个是返回的构造函数;
            function klass() {
                this.initialize.apply(this, arguments);
            };

            //为klass添加addMethods方法;
            Object.extend(klass, Class.Methods);
            //保存超类;
            klass.superclass = parent;
            klass.subclasses = [];

            if (parent) {
                subclass.prototype = parent.prototype;
                klass.prototype = new subclass;
                //把当前的类保存到父级的超类, 有什么意义呢;
                parent.subclasses.push(klass);
            };

            for (var i = 0, length = properties.length; i < length; i++)
                klass.addMethods(properties[i]);

            //避免没有initialize而报错;
            if (!klass.prototype.initialize)
                klass.prototype.initialize = function() {};

            //这个避免constructor被properties覆盖了, 重新赋值;
            klass.prototype.constructor = klass;
            return klass;
        }

        function addMethods(source) {
            var ancestor   = this.superclass && this.superclass.prototype,
                properties = Object.keys(source);

            //IE8以下可以遍历到toString和valueOf;
            if (IS_DONTENUM_BUGGY) {
                if (source.toString != Object.prototype.toString)
                    properties.push("toString");
                if (source.valueOf != Object.prototype.valueOf)
                    properties.push("valueOf");
            }

            for (var i = 0, length = properties.length; i < length; i++) {
                var property = properties[i], value = source[property];
                //没有父级就没必要走下去了 , 如果有父级, 而且value不是function那么就没必要走了;
                //如果你传:Class.create(Fn, {0:function($super){alert(1)},1:1,2:2,3:3,4:4})
                //那么$super这个方法是指向ancestor的闭包, 只要执行$super那么超类的同名方法会被执行;
                if (ancestor && Object.isFunction(value) &&
                    value.argumentNames()[0] == "$super") {
                    var method = value;
                    //返回一个闭包;
                    value = (function(m) {
                        return function() { return ancestor[m].apply(this, arguments); };
                    })(property).wrap(method);
                    /*
                     如果不用简写的话,写成这样子也是ok的,他那么写, 一下子高端起来了,我C, 就是两个闭包哇;
                     *
                    var closureFn = (function(m) {
                        return function() { return ancestor[m].apply(this, arguments); };
                     })(property);
                     value = function() {
                        var args = Array.prototype.slice.call(arguments);
                        args.unshift( closureFn );
                        //是谁执行了value,当前的this就是谁,刚好是实例对象;
                        method.apply(this, args)
                     };
                     * */
                    //修正这个闭包的valueOf为method这个方法....
                    value.valueOf = method.valueOf.bind(method);
                    value.toString = method.toString.bind(method);
                };
                //Class.create({0:0,1:1,2:2,3:3,4:4})会走这边;
                this.prototype[property] = value;
            };
            return this;
        };

        return {
            create: create,
            Methods: {
                addMethods: addMethods
            }
        };
    })();
</script>
<script>
    //__________________________________________
    //创建一个类工厂
    var Fn = Class.create({
        method0 : function() {
            console.log("method0");
            console.log(arguments);
        },
        method1 : function() {
            console.log("method1");
            console.log(arguments);
        }
    });

    //实例化该类工厂;
    var fn = new Fn();
    fn.method0(); //输出 : method0 []
    fn.method1(0,1,2,3,4); //输出 : method1 , [0, 1, 2, 3, 4];

    //SubFn , 继承了Fn;
    var SubFn = Class.create(Fn, {
        method2 : function() {
            console.log(2)
        }
    });
    (new SubFn).method2() //输出 :2
    //__________________________________________

    //__________________________________________
    //子类调用超类的同名方法的使用;
    //子类;
    var Fn = Class.create({
        0:function(){
            console.log(arguments);
            return "hehe";
        },
        1:1,
        2:2,
        3:3,
        4:4
    });

    //超类;
                            //Fn0继承了Fn;
    var Fn0 = Class.create(Fn, {
        0:function($super,arg0,arg1,arg2,arg3){
            console.log( $super( arguments ) );
            console.log(arg0+" "+arg1+" "+arg2+ " " +arg3);
        }
    });
    //实例化Fn0,执行0的方法传进去几个参数, 都会传到Fn的0方法里面, Fn0如果叫做$super的参数, $super代表超类的同名方法;
    (new Fn0)[0](10,9,8,7); //输出 三个字段,包含超类的的arguments和超类的返回,以及子类的输出: arguments5 , hehe , 10,9,8,7
    console.log(new Fn0); //输出一个实例;
    //__________________________________________

    //为Fn0的原型新加一个“nono”方法;
    Fn0.addMethods({"nono" : function() {
        console.log("you are super man");
    }});
    //实例化原型执行nono方法:
    var instance = new Fn0;
    instance.nono() //输出了:you are super man;
    //__________________________________________

    //我们现在的类方法和属性都是原型上继承下来的,只要超类的方法或者属性发生了改变, 那么子类的方法也发生了改变;
    //比如
    Fn0.prototype.nono = "someting wrong!!";
    instance.nono // 输出了== >"someting wrong!!" ...卧槽,这样可不行啊;
    //我们需要创建私有属性
    var FnBar = Class.create(Fn,{
        initialize : function() {
            this.hehe = "haha",
            this.say = function( words ) {
                console.log( words ||this.hehe );
            };
        }
    });
    var instanceBar = new FnBar();
    var FnFoo = Class.create(FnBar,{
        initialize : function() {
            this.say = function() {
                console.log("fuck! you duck!!!");
            };
        }
    });
    //prototype是基于原型继承原型的库, 而不是基于原型继承实例, 所以用起来也挺方便的;
    (new FnFoo).say();
</script>
</body>
</html>

View Code

 

 

  这款持续创建的作者是jQ的作者,你知的, 不绕;

  https://github.com/html5crew/simple-inheritance  《《==
这个是代码的源地址:

ECMAScript 7ECMAScript 8

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8">
</head>
<body>
    <script>
        /* source: https://gist.github.com/shakyShane/5944153
         *
         * Simple JavaScript Inheritance for ES 5.1 ( includes polyfill for IE < 9 )
         * based on http://ejohn.org/blog/simple-javascript-inheritance/
         *  (inspired by base2 and Prototype)
         * MIT Licensed.
         */
        (function (global) {
            "use strict";

            if (!Object.create) {
                Object.create = (function () {
                    function F() {
                    }

                    return function (o) {
                        if (arguments.length !== 1) {
                            throw new Error("Object.create implementation only accepts one parameter.");
                        }
                        F.prototype = o;
                        return new F();
                    };
                })();
            }

            var fnTest = /xyz/.test(function () {
                /* jshint ignore:start */
                xyz;
                /* jshint ignore:end */
            }) ? /\b_super\b/ : /.*/;

            // The base Class implementation (does nothing)
            function BaseClass() {
            }

            // Create a new Class that inherits from this class
            BaseClass.extend = function (props) {
                var _super = this.prototype;

                // Instantiate a base class (but only create the instance,
                // don't run the init constructor)
                var proto = Object.create(_super);

                // Copy the properties over onto the new prototype
                for (var name in props) {
                    // Check if we're overwriting an existing function
                    proto[name] = typeof props[name] === "function" &&
                            typeof _super[name] === "function" && fnTest.test(props[name]) ?
                            (function (name, fn) {
                                return function () {
                                    var tmp = this._super;

                                    // Add a new ._super() method that is the same method
                                    // but on the super-class
                                    this._super = _super[name];

                                    // The method only need to be bound temporarily, so we
                                    // remove it when we're done executing
                                    var ret = fn.apply(this, arguments);
                                    this._super = tmp;

                                    return ret;
                                };
                            })(name, props[name]) :
                            props[name];
                }

                // The new constructor
                var newClass = function () {
                    if (typeof this.init === "function") {
                        this.init.apply(this, arguments);
                    }
                };


                // Populate our constructed prototype object
                newClass.prototype = proto;

                // Enforce the constructor to be what we expect
                proto.constructor = newClass;

                // And make this class extendable
                newClass.extend = BaseClass.extend;

                return newClass;
            };

            // export
            global.Class = BaseClass;
        })(this);
    </script>
    <script>
        var Fn = function() {};
        //对继承的插件进行引用;
        Fn.extend = window.Class.extend;
        Fn.prototype.lala = 1;
        Fn.prototype.say = function() {
            alert( this.lala );
        };
        var Foo = Fn.extend({
            dudu:2,
            init:function(){
                this.name="nono"
            },
            dayDudu:function(){
                alert(this.dudu);
            }
        })
    </script>
    </body>
</html>

View Code

 

 

  执行 new Foo打印出目标组织如下:

ECMAScript 9

 

  pjs这个类工厂的github地址是:git://github.com/jayferd/pjs ,挺有名的js类工厂仓库,
写了源码分析, 关于代码我虽非吐槽了,你看了即懂得了, 不了真心实意很便宜之;

ECMAScript 10ECMAScript 11

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>
<body>
<script>
var P = (function(prototype, ownProperty, undefined) {
  // helper functions that also help minification
  function isObject(o) { return typeof o === 'object'; }
  function isFunction(f) { return typeof f === 'function'; }

  // a function that gets reused to make uninitialized objects
  function BareConstructor() {}

  function P(_superclass /* = Object */, definition) {
    // handle the case where no superclass is given
      //如果没有超类,那么超类就设置为Object,definition为对象或者是fn都行
      //是对象的话会把对象的所有属性和方法复制到返回的类原型,
      //是函数会传给函数有关返回类的原型(引用)等参数;
    if (definition === undefined) {
      definition = _superclass;
      _superclass = Object;
    };

    // C is the class to be returned.
    //
    // It delegates to instantiating an instance of `Bare`, so that it
    // will always return a new instance regardless of the calling
    // context.
    //
    //  TODO: the Chrome inspector shows all created objects as `C`
    //        rather than `Object`.  Setting the .name property seems to
    //        have no effect.  Is there a way to override this behavior?
      //无论你是使用 new还是直接运行都会返回C的实例;
    function C() {
      var self = new Bare;
        //如果创建的实例有init会执行init方法, init这个函数里面放的是私有的属性;
      if (isFunction(self.init)) self.init.apply(self, arguments);
      return self;
    }

    // C.Bare is a class with a noop constructor.  Its prototype is the
    // same as C, so that instances of C.Bare are also instances of C.
    // New objects can be allocated without initialization by calling
    // `new MyClass.Bare`.
    function Bare() {}
    C.Bare = Bare;

    // Set up the prototype of the new class.
      //指定超类的原型 到BareConstructor, 公用一个函数到BareConstructor,专门用来实例化超类;
    var _super = BareConstructor[prototype] = _superclass[prototype];
      //proto为Bare原型的引用;
      //实例化的超类的实例指向了C和Bare的Prototype,主要是Bare的prototype,因为类工厂返回的实例就是Bare的实例;
    var proto = Bare[prototype] = C[prototype] = new BareConstructor;

    // other variables, as a minifier optimization
    var extensions;


    // set the constructor property on the prototype, for convenience
    proto.constructor = C;

    //这个超类的mixin会重新调用P返回原型重新赋值给Bare和C,返回C, 方便无new实例化;
    C.mixin = function(def) {
      Bare[prototype] = C[prototype] = P(C, def)[prototype];
      return C;
    };

    //C.open 这个方法可以用来为这个类添加原型
    return (C.open = function(def) {
        //重新定义extensions为一个空对象, C.open打开或者第一次打开的时候重新定义, 写成var extensions = {}; 也行,个人感觉没有问题;
      extensions = {};

      if (isFunction(def)) {
        // call the defining function with all the arguments you need
        // extensions captures the return value.
                                //proto指向了C和Bare的原型,要添加原型就往这个对象extend方法即可;
                                //也可以为这个函数返回对象作为原型的属性;
        extensions = def.call(C, proto, _super, C, _superclass);
      }
      else if (isObject(def)) {
        // if you passed an object instead, we'll take it
        extensions = def;
      };

        //继承属性到超类;
      // ...and extend it
      if (isObject(extensions)) {
        for (var ext in extensions) {
          if (ownProperty.call(extensions, ext)) {
            proto[ext] = extensions[ext];
          };
        };
      };

        //没有init就把init设置为超类;
      // if there's no init, we assume we're inheriting a non-pjs class, so
      // we default to applying the superclass's constructor.
      if (!isFunction(proto.init)) {
        proto.init = _superclass;
      }

      return C;
    })(definition);
  }

  // ship it
  return P;

  // as a minifier optimization, we've closured in a few helper functions
  // and the string 'prototype' (C[p] is much shorter than C.prototype)
})('prototype', ({}).hasOwnProperty);
</script>

<script>
//直接创建一个类
var Fn = P({
    0:0,
    1:1
});
console.log( new Fn() ); //输出: Bare {0: 0, 1: 1, constructor: function, init: function}
console.log( (new Fn()).init() ) //如果没有init, 那么init出来默认为 Object {}

//让FnBar继承Fn
var FnBar = P(Fn,{
    2:2,
    3:3,
    4:4
});
console.log( new FnBar ); //输出: Bare {2: 2, 3: 3, 4: 4, constructor: function, 0: 0, 1: 1, init: function}

//为FnFoo添加额外的方法和属性;
var FnFoo = FnBar.open({
    5:5,
    6:6
});
console.log( new FnFoo ); //输出: Bare {2: 2, 3: 3, 4: 4, 5: 5, 6: 6, constructor: function, 0: 0, 1: 1, init: function}

//各种各样的继承方式 你都可以用
var FnFoo0 = FnFoo.mixin({
    7:7,
    8:8
});
console.log( new FnFoo0); //输出: Bare {7: 7, 8: 8, constructor: function, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 0: 0, 1: 1, init: function}

//____________________________________-_-_______________
//直接创建一个类
var Fn = P({
    0:0,
    1:1,
    init : function() {
        this.name = "nono";
        console.log(this);
    }
});
(new Fn).init(); // 输出: Bare {name: "nono", 0: 0, 1: 1, constructor: function, init: function};

//通过C.open的方式为Fn添加超类
var FnBar = Fn.open(function(  proto, _super, C, _superclass ) {
    proto.style = "gangnanStyle";
    proto.job = "superWebDevoloper";
    proto.say = function() {
        console.log( this.job + " __ " + this.job);
    };
});
(new FnBar).say(); //输出: superWebDevoloper __ superWebDevoloper

//通过传入function的方式为构造函数添加超类;
// 该方法不但继承了FnBar, 而且在第二个Fn的参数中为构造函数添加了sayWhat方法, 该函数的返回也会作为原型被添加到类原型上。。。。;
var FF = P(FnBar, function( proto, _super, C, _superclass ) {
    proto.sayWhat = function() {
        console.log( "funky world!" );
    };
    return {
        sayHi : function() {
            console.log( "monkey world!" );
        }
    };
});
console.log( new FF );//输出: Bare {name: "nono", constructor: function, sayWhat: function, 0: 0, 1: 1, init: function, style: "gangnanStyle"…};
(new FF).sayWhat();  //输出: funky world!
(new FF).sayHi();  //输出:monkey world!
</script>
</body>
</html>

View Code

 

 

  每一个丁还要发平等切开属于自己之安静天空, 在那边没有压力, 只有团结
, 和温馨身体的对话;

 

 

  

  最后提供有参照的链接:

    javascript
类属性、类方式、类实例、实例属性、实例方法、prototype、__proto__
测试与总: 

      http://www.cnblogs.com/mrsunny/archive/2011/05/09/2041185.html

     JS的构造函数:

      http://www.cnblogs.com/jikey/archive/2011/05/13/2045005.html

*    浅析Javascript原型继承:ECMAScript*

*      *http://blog.csdn.net/kittyjie/article/details/4380918**