<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      發(fā)布我的Javascript OOP框架YOOP

      大家好!今天我正式發(fā)布我的OOP框架YOOP!該框架將幫助開發(fā)者更好地進(jìn)行面向?qū)ο缶幊獭?/p>

      當(dāng)前版本號(hào):v1.1

      GitHub下載地址

      介紹

      該框架包含接口、抽象類、類。

      接口Interface可以繼承多個(gè)接口,可以定義方法、屬性。

      抽象類AClass可以繼承多個(gè)接口、一個(gè)抽象類,可以定義構(gòu)造函數(shù)、公有成員、私有成員、保護(hù)成員、靜態(tài)成員、虛成員、抽象成員。

      類Class可以繼承多個(gè)接口、一個(gè)抽象類或類,可以定義構(gòu)造函數(shù)、公有成員、私有成員、保護(hù)成員、靜態(tài)成員、虛成員。 

      子類調(diào)用父類成員

      在子類中,可以使用this.base()來(lái)調(diào)用父類同名方法。也可以使用this.baseClass來(lái)訪問(wèn)父類的原型。

      主要的語(yǔ)法規(guī)則

      類Class:

      1. 創(chuàng)建實(shí)例時(shí)調(diào)用構(gòu)造函數(shù)。
      2. 驗(yàn)證是否實(shí)現(xiàn)了接口的方法、屬性,如果沒有實(shí)現(xiàn)會(huì)拋出異常。
      3. 驗(yàn)證是否實(shí)現(xiàn)了父類的抽象成員,如果沒有實(shí)現(xiàn)會(huì)拋出異常。
      4. 只能繼承一個(gè)類(AClass或Class),否則拋出異常.
      5. 不能定義抽象成員,否則拋出異常。

      抽象類AClass:

      1. 可以聲明構(gòu)造函數(shù),供子類Class調(diào)用。
      2. 抽象類如果繼承類Class,會(huì)拋出異常。
      3. 不用實(shí)現(xiàn)接口,可以交給子類Class實(shí)現(xiàn)。
      4. 不用實(shí)現(xiàn)父類抽象成員,可以交給子類Class實(shí)現(xiàn)。
      5. 只能繼承一個(gè)抽象類AClass,否則拋出異常。

      接口Interface:

      1. 接口只能繼承接口,否則拋出異常。 

      使用YOOP

      YOOP支持AMD、CMD、CommonJS規(guī)范,可在Sea.js、node.js中使用:

      var yoop = require("./YOOP.js");
      
      yoop.Class({});

      也可以通過(guò)script標(biāo)簽在頁(yè)面上直接引用

      頁(yè)面上引用script:

      <script src="./YOOP.js"></script>

      然后通過(guò)命名空間YYC來(lái)使用:

      YYC.Class({});

      用法

      接口

      定義接口

      只有方法:

      var A = YYC.Interface("method1", "method2");

      只有屬性:

      var A = YYC.Interface([], ["attribute1", "attribute2"]);

      既有方法又有屬性:

      var A = YYC.Interface(["method1", "method2"], ["attribute1", "attribute2"]);

      繼承接口

      var A = YYC.Interface(["method1", "method2"],["attribute1", "attribute2"]);
      var B = YYC.Interface(A, "m1", "m2");
      var C = YYC.Interface([A], ["m1", "m2"], ["a1", "a2"]);
      var D = YYC.Interface([A, B], ["m1", "m2"], ["a1", "a2"]);

      抽象類

      定義抽象類

      var A = YYC.AClass({
          Init: function () { //構(gòu)造函數(shù)
          },
          Protected: {    //保護(hù)成員
              Abstract: { //保護(hù)抽象成員
              },
              Virtual: {  //保護(hù)虛方法
              },
              P_proA: true,   //保護(hù)屬性
             P_proM: function () { }    //保護(hù)方法
          },
          Public: {   //公有成員
              Abstract: { //公有抽象成員
              },
              Virtual: {  //公有虛方法
              },
              pubM: function () { },  //公有方法
            pubA: 0    //公有屬性
          },
          Private: {  //私有成員
              _priA: "",   //私有屬性
              _priM: function () { } //私有方法
          },
          Abstract: { //公有抽象成員
          },
          Virtual: {  //公有虛方法
          }
      });
      View Code

      繼承抽象類

      var A = YYC.AClass({});
      var B = YYC.AClass(A, {});
      var C = YYC.AClass({Class: A}, {}); 
      View Code

      繼承接口

      var A = YYC.Interface("m1");
      var B = YYC.Interface("m2");
      var C = YYC.AClass({ Interface: A }, {
          Public: {
              m1: function () { }
          }
      });
      var D = YYC.AClass({ Interface: [A, B] }, {
          Public: {
              m1: function () { },
              m2: function () { }
          }
      });
      View Code

      繼承接口和抽象類

      var A = YYC.Interface("m1");
      var B = YYC.Interface(["m2"], ["a"]);
      var C = YYC.AClass({});
      var D = YYC.AClass({ Interface: [A, B], Class: C }, {
          Public: {
              m1: function () { },
              a: 0
          }
      });
      View Code

      定義類

      var A = YYC.Class({
                      Init: function () { //構(gòu)造函數(shù)
                      },
                      Protected: {    //保護(hù)成員
                          Virtual: {  //保護(hù)虛方法
                          },
                          P_proA: true,   //保護(hù)屬性
                          P_proM: function () { }    //保護(hù)方法
                      },
                      Public: {   //公有成員
                          Virtual: {  //公有虛方法
                          },
                          pubM: function () { },  //公有方法
                          pubA: 0    //公有屬性
                      },
                      Private: {  //私有成員
                          _priA: "",   //私有屬性
                          _priM: function () { } //私有方法
                      },
                      Virtual: {  //公有虛方法
                      }
                  });
      View Code

      繼承抽象類

      var A = YYC.AClass({});
      var B = YYC.AClass(A, {});
      var C = YYC.AClass({ Class: A }, {});
      View Code

      繼承類

      var A = YYC.Class({});
      var B = YYC.Class(A, {});
      var C = YYC.Class({ Class: A }, {});
      View Code

      繼承接口

      var A = YYC.Interface("m1");
      var B = YYC.Interface("m2");
      var C = YYC.Class({ Interface: A }, {
          Public: {
              m1: function () { }
          }
      });
      var D = YYC.Class({ Interface: [A, B] }, {
          Public: {
              m1: function () { },
              m2: function () { }
          }
      });
      View Code

      繼承接口和抽象類/類

      var A = YYC.Interface("m1");
      var B = YYC.Interface(["m2"], ["a"]);
      var C = YYC.AClass({});
      var D = YYC.Class({});
      var E = YYC.AClass({ Interface: [A, B], Class: C }, {
          Public: {
              m1: function () { },
              a: 0
          }
      });
      var F = YYC.AClass({ Interface: [A, B], Class: D }, {
          Public: {
              m1: function () { },
              a: 0
          }
      });
      View Code

      構(gòu)造函數(shù)

      var A = YYC.Class({
        Init: function(t){
          this.value = t;
        }
      });
      var a = new A(100);
      console.log(a.value);  //100
      View Code

      靜態(tài)成員

      使用“類.靜態(tài)成員”的形式來(lái)調(diào)用靜態(tài)成員。這里靜態(tài)成員實(shí)質(zhì)是類(function,function也是對(duì)象)的成員。

      注意!靜態(tài)方法中的this指向類,不是指向類的實(shí)例!

      var A = YYC.Class({
          Static: {
              a: 100,
              method1: function () {
                  return 200;
              },
              method2: function () {
                   this.k = 300;
              }
          }
      });
      
      A.method2();
      
      console.log(A.a);   //100
      console.log(A.method1());    //200
      console.log(A.k);   //300
      View Code

      類的成員互相調(diào)用

      使用this來(lái)調(diào)用。

      var A = YYC.Class({
          Private: {
              _a: 100
          },
          Public: {
              method: function (t) {
                  return this._a;
              }
          }
      });
      var a = new A();
      console.log(a.method);  //100
      View Code

      子類調(diào)用父類

      使用this.base()可調(diào)用父類同名函數(shù)。

      使用this.baseClass.xx.call(this, xx)可調(diào)用父類的成員。

      var A = YYC.AClass({
                          Init: function () {
                              this.p = 100;
                          },
                          Public: {
                              method1: function () {
                                  this.m = 300;
                              },
                              method2: function () {
                                  return 100;
                              }
                          }
                      });
                      var B = YYC.Class(A, {
                          Init: function () {
                              this.base();
                          },
                          Private: {
                              _a: 100
                          },
                          Public: {
                              method1: function (t) {
                                  this.base();
                                  return this.baseClass.method2.call(this, null) + this._a;
                              }
                          }
                      });
                      var b = new B();
                      console.log(b.method1());  //200
                      console.log(b.p);  //100
                      console.log(b.m);  //300
      View Code

      父類調(diào)用子類

      var A = YYC.AClass({
          Public: {
              method: function () {
                  console.log(this.value);
              }
          }
      });
      var B = YYC.Class(A, {
          Public: {
              value: 100
          }
      });
      var b = new B();
      b.method(); //100
      View Code

      覆寫父類方法,實(shí)現(xiàn)接口成員、抽象成員

      var A = YYC.Interface("m1");
      var B = YYC.AClass({ Interface: A }, {
          Protected: {
              Abstract: {
                  P_method: function () { }
              }
          },
          Public: {
              method: function () { }
          }
      });
      var C = YYC.Class(B, {
          Protected: {
              P_method: function () {
                  console.log("實(shí)現(xiàn)抽象方法");
              }
          },
          Public: {
              method: function () {
                  console.log("覆蓋父類同名方法");
              },
              m1: function () {
                  console.log("實(shí)現(xiàn)接口");
              }
          }
      });
      View Code

      其它API

      stubParentMethod、stubParentMethodByAClass

      讓父類(Class/AClass)指定方法不執(zhí)行。

      測(cè)試用例如下:

      describe("stubParentMethod", function () {
              var sandbox = null;
              var A = null,
                  B = null,
                  C = null,
                  a = null,
                  b = null,
                  c = null;
      
              beforeEach(function () {
                  A = YYC.Class({
                      Public: {
                          done: function () {
                              throw new Error("");
                          }
                      }
                  });
                  B = YYC.Class(A, {
                      Public: {
                          done: function () {
                              this.baseClass.done.call(this, null);
                          }
                      }
                  });
                  C = YYC.Class(B, {
                      Public: {
                          a: 0,
      
                          done: function () {
                              this.base();
      
                              this.a = 100;
                          }
                      }
                  });
                  a = new A();
                  b = new B();
                  c = new C();
      
                  sandbox = sinon.sandbox.create();
              });
              afterEach(function () {
                  sandbox.restore();
              });
      
              it("讓父類指定方法不執(zhí)行,用于Class的測(cè)試方法中調(diào)用了父類方法的情況", function () {
                  expect(function () {
                      b.done();
                  }).toThrow();
                  expect(function () {
                      c.done();
                  }).toThrow();
      
                  b.stubParentMethod(sandbox, "done");
                  c.stubParentMethod(sandbox, "done");
      
                  expect(function () {
                      b.done();
                  }).not.toThrow();
                  expect(function () {
                      c.done();
                  }).not.toThrow();
              });
              it("可將父類指定方法替換為假方法", function () {
                  c.stubParentMethod(sandbox, "done", function () {
                      this.val = 1;
                  });
      
                  c.done();
      
                  expect(c.val).toEqual(1);
              });
              it("可按照sinon->stub API測(cè)試父類指定方法的調(diào)用情況", function () {
                  c.stubParentMethod(sandbox, "done");
      
                  c.done();
      
                  expect(c.lastBaseClassForTest.done.calledOnce).toBeTruthy();
              });
          });
      
          describe("stubParentMethodByAClass", function () {
              var sandbox = null;
              var A = null,
                  B = null,
                  t = null;
      
              beforeEach(function () {
                  A = YYC.AClass({
                      Public: {
                          a: 0,
                          done: function () {
                              throw new Error("");
                          }
                      }
                  });
                  B = YYC.AClass(A, {
                      Public: {
                          done: function () {
                              this.base();
                          }
                      }
                  });
      
                  //想要測(cè)試B的done方法,必須先建一個(gè)空子類繼承B,然后測(cè)試空子類的done方法
                  function getInstance() {
                      var T = YYC.Class(B, {
                      });
      
                      return new T();
                  }
      
                  t = getInstance();
      
                  sandbox = sinon.sandbox.create();
              });
              afterEach(function () {
                  sandbox.restore();
              });
      
              it("讓父類指定方法不執(zhí)行,用于AClass的測(cè)試方法中調(diào)用了父類方法的情況", function () {
                  expect(t.done).toThrow();
      
                  t.stubParentMethodByAClass(sandbox, "done");
      
                  expect(t.done).not.toThrow();
              });
              it("可將父類指定方法替換為假方法", function () {
                  t.stubParentMethodByAClass(sandbox, "done", function () {
                      this.val = 1;
                  });
      
                  t.done();
      
                  expect(t.val).toEqual(1);
              });
              it("可按照sinon->stub API測(cè)試父類指定方法的調(diào)用情況", function () {
                  t.stubParentMethodByAClass(sandbox, "done");
      
                  t.done();
      
                  expect(t.lastBaseClassForTest.done.calledOnce).toBeTruthy();
              });
          });
      View Code

      isInstanceOf

      判斷是否為類的實(shí)例。

      測(cè)試用例如下:

           describe("isInstanceOf", function () {
              it("直接判斷是否為Class的實(shí)例", function () {
                  var A = YYC.Class({});
      
                  expect(new A().isInstanceOf(A)).toBeTruthy();
              });
              describe("測(cè)試?yán)^承抽象類時(shí)的情況", function () {
                  it("測(cè)試1", function () {
                      var A = YYC.AClass({});
                      var B = YYC.Class(A, {});
      
                      expect(new B().isInstanceOf(B)).toBeTruthy();
                      expect(new B().isInstanceOf(A)).toBeTruthy();
                  });
                  it("測(cè)試2", function () {
                      var A = YYC.AClass({});
                      var B = YYC.AClass(A, {});
                      var C = YYC.Class(B, {});
                      var D = YYC.Class(A, {});
      
                      expect(new C().isInstanceOf(B)).toBeTruthy();
                      expect(new C().isInstanceOf(A)).toBeTruthy();
                      expect(new D().isInstanceOf(A)).toBeTruthy();
                      expect(new D().isInstanceOf(B)).toBeFalsy();
                  });
              });
      
              describe("測(cè)試?yán)^承接口時(shí)的情況", function () {
                  it("測(cè)試1", function () {
                      var A = YYC.Interface("a");
                      var B = YYC.Class({Interface: A}, {
                          Public: {
                              a: function () {
                              }
                          }
                      });
      
                      expect(new B().isInstanceOf(B)).toBeTruthy();
                      expect(new B().isInstanceOf(A)).toBeTruthy();
                  });
                  it("測(cè)試2", function () {
                      var A = YYC.Interface("a");
                      var B = YYC.Interface("b");
                      var C = YYC.Interface([A, B], "c");
                      var D = YYC.Class({Interface: C}, {
                          Public: {
                              a: function () {
                              },
                              b: function () {
                              },
                              c: function () {
                              }
                          }
                      });
      
                      expect(new D().isInstanceOf(C)).toBeTruthy();
                      expect(new D().isInstanceOf(B)).toBeTruthy();
                      expect(new D().isInstanceOf(A)).toBeTruthy();
                  });
              });
      
              it("綜合測(cè)試", function () {
                  var A = YYC.Interface("a1");
                  var B = YYC.Interface(A, "a2");
                  var C = YYC.AClass({Interface: B}, {
                      Public: {
                          a1: function () {
                          },
                          a2: function () {
                          }
                      }
                  });
                  var D = YYC.AClass(C, {
                      Public: {
                          a1: function () {
                          },
                          a2: function () {
                          }
                      }
                  });
                  var E = YYC.Class(C, {
                  });
                  var F = YYC.Class(E, {
                  });
                  var G = YYC.Class({Interface: B, Class: D}, {
                  });
      
                  expect(new E().isInstanceOf(C)).toBeTruthy();
                  expect(new E().isInstanceOf(B)).toBeTruthy();
                  expect(new E().isInstanceOf(A)).toBeTruthy();
      
                  expect(new F().isInstanceOf(E)).toBeTruthy();
                  expect(new F().isInstanceOf(C)).toBeTruthy();
                  expect(new F().isInstanceOf(B)).toBeTruthy();
                  expect(new F().isInstanceOf(A)).toBeTruthy();
      
                  expect(new G().isInstanceOf(B)).toBeTruthy();
                  expect(new G().isInstanceOf(D)).toBeTruthy();
      
                  expect(new G().isInstanceOf(E)).toBeFalsy();
              });
          }); 
      View Code

      YOOP.version

      返回當(dāng)前版本號(hào)。

      測(cè)試用例如下:

          it("獲得當(dāng)前版本號(hào)", function () {
             expect(YYC.YOOP.version).toBeString();
          });

      約定

      在該框架的實(shí)現(xiàn)中,類的實(shí)例可以訪問(wèn)類的公有成員、保護(hù)成員、私有成員,所有成員都是添加到類的原型中(如果是繼承,則將父類的成員添和子類的成員都添加到子類的原型中),框架只是從語(yǔ)義上區(qū)分了成員的訪問(wèn)權(quán)限,在機(jī)制上沒有對(duì)成員的訪問(wèn)權(quán)限設(shè)任何限制!

      因此,用戶需要采用命名約定的方式來(lái)區(qū)分不同的成員,需要自覺遵守訪問(wèn)權(quán)限規(guī)則(如類的實(shí)例只能訪問(wèn)公有成員;不能訪問(wèn)其它類的私有成員;子類可以訪問(wèn)父類的保護(hù)成員等等)。

      私有成員和保護(hù)成員的建議命名約定

      基類的私有成員以“_”開頭,保護(hù)成員以“P_”開頭。

      在繼承樹中,第一層類私有成員以“_”開頭,第二層類私有成員以“__”開頭,以此類推,從而區(qū)分不同層級(jí)中同名的私有成員。

      所有層級(jí)中的保護(hù)成員前綴都為“P_”(原因見后面“為什么每層子類的保護(hù)成員前綴都一樣”的討論)。

      用戶也可以將第一層子類的私有成員前綴設(shè)為“_1_”,第二層子類的私有成員設(shè)為“_2_”。。。。。。

      前綴設(shè)置規(guī)則用戶可自訂,只要在繼承中使不同層級(jí)的類的私有成員不重名即可。

      見下面的實(shí)例代碼:

      不繼承接口

      var A = YYC.AClass({    //私有成員以“_”開頭,保護(hù)成員以“P_”開頭
          Private: {
              _value: 0,
              _method: function () {
              }
          },
          Protected: {
              P_value: 0,
      
              Virtual: {
                  P_method: function () {
                  }
              }
          }
      });
      var B = YYC.Class(A, {  //私有成員以“__”開頭,保護(hù)成員以“P_”開頭
          Private: {
              __value: 0,
              __method: function () {
              }
          },
          Protected: {
              P_method: function () {
              }
          }
      });

      繼承接口

      var I = YYC.Interface("method");
      var A = YYC.AClass({ Interface: I }, {   //私有成員以“_”開頭,保護(hù)成員以“P_”
          Private: {
              _value: 0,
              _method: function () {
              }
          },
          Protected: {
              P_value: 0,
      
              Virtual: {
                  P_method: function () {
                  }
              }
          }
      });
      var B = YYC.Class(A, {  //私有成員以“__”開頭,保護(hù)成員以“P_”
          Private: {
              __value: 0,
              __method: function () {
              }
          },
          Protected: {
              P_method: function () {
              }
          },
          Public: {
              method: function () {
              }
          }
      });

      為什么每層子類的私有前綴最好不一樣?

      如果子類與父類有同名的私有成員時(shí),當(dāng)子類調(diào)用父類成員時(shí),可能會(huì)出現(xiàn)父類成員調(diào)用子類的私有成員。

      見下面的示例代碼:

      var A = YYC.AClass({
          Private: {
              _val: 100
          },
          Public: {
              getVal: function () {
                  return this._val;
              }
          }
      });
      
      var B = YYC.Class(A, {
          Private: {
              _val: 200
          },
          Public: {
              getVal: function () {
                  return this.base();
              }
          }
      });
      
      expect(new B().getVal()).toEqual(100);  //失?。∑谕祷谹->_val(100),實(shí)際返回的是B->_val(200)

      為什么每層子類的保護(hù)成員前綴都一樣?

      如果父類與子類的保護(hù)成員同名,則父類的該保護(hù)成員一般都是設(shè)計(jì)為虛成員,專門供子類覆寫的。因此當(dāng)子類調(diào)用父類成員時(shí),本來(lái)就期望父類成員調(diào)用子類覆寫的保護(hù)成員。

      見下面的示例代碼:

      var A = YYC.AClass({
          Protected: {
              Virtual: {
                  P_val: 100
              }
          },
          Public: {
              getVal: function () {
                  return this.P_val;
              }
          }
      });
      
      var B = YYC.Class(A, {
          Protected: {
              P_val: 200
          },
          Public: {
              getVal: function () {
                  return this.base();
              }
          }
      });
      
      expect(new B().getVal()).toEqual(200);  //由于B覆寫了A的虛屬性P_val,因此B->getVal應(yīng)該返回B覆寫后的P_val(200)

      baseClass

      為了防止子類的prototype.baseClass覆蓋父類prototype.baseClass,在子類繼承父類時(shí),用戶需要先判斷父類prototype.baseClass是否存在。如果存在,則加上前綴“_”,如“_baseClass”。如果加上前綴后依然存在,則再加上前綴“_”,如“__baseClass”。以此類推。

      如:

                      var A1 = YYC.AClass({
                          Public: {
                              arr: [],
                              a: function () {
                                  this.arr.push(1);
                              }
                          }
                      });
                      var A2 = YYC.AClass(A1, {
                          Public: {
                              a: function () {
                                  this.arr.push(2);
                                  this.baseClass.a.call(this, null);  //調(diào)用A1.a
                              }
                          }
                      });
                      var B = YYC.Class(A2, {
                          Public: {
                              a: function () {
                                  this.arr.push(3);
                                  this._baseClass.a.call(this, null); //調(diào)用A2.a
                                  this.baseClass.a.call(this, null);  //調(diào)用A1.a
      
                                  return this.arr;
                              }
                          }
                      });
                      var b = new B();
      
                      expect(b.a()).toEqual([3, 2, 1, 1]);
      View Code

      注意事項(xiàng)

      子類使用this.baseClass調(diào)用父類成員時(shí),要將父類成員的this指向子類。

      錯(cuò)誤的寫法:

      var A = YYC.AClass({
          Public: {
              method: function () {
                  this.p = 100;
              }
          }
      });
      var B = YYC.Class(A, {
          Public: {
              method: function () {
                  this.baseClass.method();
              }
          }
      });
      var b = new B();
      b.method();
      console.log(b.p);   //此處為undefined,而不是100!

      正確的寫法:

      var A = YYC.AClass({
          Public: {
              method: function () {
                  this.p = 100;
              }
          }
      });
      var B = YYC.Class(A, {
          Public: {
              method: function () {
                  this.baseClass.method.call(this, null);
              }
          }
      });
      var b = new B();
      b.method();
      console.log(b.p);   //100

      已解決的問(wèn)題

      YOOP框架目前已解決了下面的問(wèn)題:

      1、同一個(gè)類的實(shí)例之間不應(yīng)該共享屬性。

      問(wèn)題描述

      參考下面的代碼:

                  var A = YYC.Class({
                      Init: function () {
                      },
                      Public: {
                          a:[]
                      }
                  });
      
                  var t = new A();
                  t.a.push("a");
                  var m = new A();
      
                  expect(t.a).toEqual(["a"]);
                  expect(m.a).toEqual([]);    //失?。?shí)際為["a"]!

      原因分析

      因?yàn)閅OOP將類的成員都加入到類的原型對(duì)象中,而類實(shí)例的成員都是鏈接自類的原型對(duì)象,所以同一個(gè)類的實(shí)例之間成員共享。

      解決方案

      在Class的構(gòu)造函數(shù)中深拷貝原型的屬性到實(shí)例中,不拷貝原型的方法,從而同一個(gè)類的實(shí)例之間共享同一原型對(duì)象的方法,但它們的屬性相互獨(dú)立。

      2、繼承于同一父類的子類實(shí)例之間不應(yīng)該共享屬性。

      問(wèn)題描述

      參考下面的代碼

                  var Parent = YYC.AClass({
                      Init: function () {
                          console.log("Parent Init!");
                      },
                      Public: {
                          a: []
                      }
                  });
                  var Sub1 = YYC.Class(Parent, {
                      Init: function () {
                      },
                      Public: {
                      }
                  });
                  var Sub2 = YYC.Class(Parent, {
                      Init: function () {
                      }
                  });
      
                  var t = new Sub1();
                  t.a.push("a");
                  var k = new Sub2();
      
                  expect(t.a).toEqual(["a"]);
                  expect(k.a).toEqual([]);    //失敗!實(shí)際為["a"]!

      原因分析

      目前是通過(guò)原型繼承的方式來(lái)實(shí)現(xiàn)繼承的。這樣子類之間的成員都鏈接自父類的原型對(duì)象,從而會(huì)造成同一父類的子類實(shí)例之間成員共享。

      解決方案

      修改類繼承方式,通過(guò)“深拷貝父類原型所有成員到子類中”的方式實(shí)現(xiàn)繼承,從而同一父類的子類實(shí)例之間的成員相互獨(dú)立。

       缺點(diǎn)

      只是從語(yǔ)義上約定了訪問(wèn)權(quán)限,而沒有從機(jī)制上限制訪問(wèn)權(quán)限。

      如可以根據(jù)命名約定區(qū)分類的公有成員、保護(hù)成員、私有成員,但是類的實(shí)例卻可以訪問(wèn)類的所有成員。

      版本歷史

      2013-06-07 發(fā)布YOOP v1.0 

      2014-08-26 發(fā)布YOOP v1.1 

      1、類實(shí)例增加isInstanceOf方法,用于判斷是否為類的實(shí)例,適用于接口繼承、類繼承等情況

      2、protected方法也可以使用this.base來(lái)訪問(wèn)父類同名方法了

      3、解決了“若一個(gè)方法中調(diào)用其它方法,則它們的this.base會(huì)互相干擾”的問(wèn)題

      4、增加stubParentMethod和stubParentMethodByAClass方法,該方法讓父類(Class/AClass)指定方法不執(zhí)行,用于Class的測(cè)試方法中調(diào)用了父類方法的情況(如調(diào)用了this.base()或this.baseClass.xxx)

      5、現(xiàn)在支持AMD、CMD、CommonJS規(guī)范了

      6、增加YYC.YOOP.version屬性,用于獲得當(dāng)前版本號(hào) 

      7、Class的構(gòu)造函數(shù)F中現(xiàn)在只拷貝原型的屬性到實(shí)例中,從而同一個(gè)類的實(shí)例之間共享同一原型對(duì)象的方法,但屬性相互獨(dú)立。

      posted @ 2013-06-07 16:18  楊元超  閱讀(3335)  評(píng)論(18)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产av不卡一区二区| 亚洲av永久无码精品天堂久久| 国产永久免费高清在线| 青青国产揄拍视频| 欧洲精品色在线观看| 亚洲aⅴ无码专区在线观看q| 精品久久久无码人妻中文字幕| 亚洲综合无码日韩国产加勒比| 国产精品午夜无码AV天美传媒 | 精品人妻av区乱码| 国产在线精品中文字幕| av中文字幕在线二区| 国产精品自在拍在线播放| 亚洲最大日韩精品一区| 中文字幕V亚洲日本在线电影| 亚洲国产精品男人的天堂| 中文精品无码中文字幕无码专区| 久久精品波多野结衣| 日本公妇乱偷中文字幕| 新久久国产色av免费看| 在线高清免费不卡全码| 国产福利社区一区二区| 日韩高清不卡一区二区三区| 人妻无码中文字幕| 天堂网在线.www天堂在线资源| 国产精品视频一区二区噜噜 | 99久久激情国产精品| 久久人人爽人人爽人人av| 2020国产成人精品视频| 亚洲人成人网站色www| 国内精品久久久久影院日本| 麦盖提县| 亚洲精品日韩在线观看| 夜夜夜高潮夜夜爽夜夜爰爰| 午夜精品视频在线看| 欧美日本激情| 欧美、另类亚洲日本一区二区| 亚洲成av人片在www鸭子| 久久综合色之久久综合色| 国产精品香蕉在线观看不卡| 国产在线国偷精品免费看|