継承:非構造関数式

4723 ワード

Javascript , (keyed collections), 。( , )純粋なプロトタイプモードでは、クラスの概念を捨てて、対象に抱擁するべきである.constructorの概念がなくなったので、継承はより簡単になります.子オブジェクトは父の属性/方法を継承することができます.
方法1:親オブジェクトを継承するために仲介空構造関数を作成し、子オブジェクトを仲介構造関数で生成した例によって親オブジェクトを継承します.
/**
 * @param {object} o -         
 */
function extendsObject(o) {
  var F = function() {};
  F.prototype = o;
  return new F;
}
//    
var parent_1 = { //                ,                    
  name: 'parent_1',
  sayName: function () {
    return this.name;
  }
};
//    
var c1 = extendsObject(parent_1);
c1.uber = parent_1; //         
//            ,  ,      ,        (differential inheritance)
//             ,                  
c1.name = 'child_1';
//        
console.log(c1.sayName()); // child_1
//               
console.log(c1.uber.sayName()); // parent_1
方法二:子オブジェクトの直接浅いコピーの親オブジェクトのプロパティ
/**
 * @param {object} o -         
 */
function shallowCopyObject(o) {
  var c = {};
  for(var k in o) {
    c[k] = o[k];
  }
  c.uber = o;
  return c;
}
var parent_2 = {
  name: 'parent_2',
  children: ['foo', 'bar'], //            “    ”,                ,             (    )
  sayName: function() {
    return this.name;
  }
};
var c2 = shallowCopyObject(parent_2); //   ,c2   parent_2      
//     ,       children         ,       ,
//  parent_2.children                ,    ,     children     ,
//         ,    ,  :
c2.children[0] = 'ugly_foo'; //     “    ”      
console.log(parent_2.children); // ['ugly_foo', 'bar']
方法3:子オブジェクトは直接親オブジェクトの属性を深くコピーします.
function deepCopyObject(o) {
  var c = {}, t;
  for (var k in o) {
    if (typeof o[k] === 'object') {
      c[k] = (o[k].constructor === Array) ? [] : {};
      c[k] = deepCopyObject(o[k]);
    } else {
      c[k] = o[k];
    }
  }
  c.uber = o;
  return c;
}
上記のコードに問題があります.親オブジェクトの各引用タイプの属性は、いずれもuber属性を発生し、この引用タイプの属性を指します.以下を改善します.
function deepCopyObject() {
  //     (closure),      root             
  var root = true;
  return function _deepCopyObject(o) {
      var c = {};
      if (root) { //   ,             uber  ,      
          c.uber = o;
          root = false;
      }
      for (var k in o) {
          if (typeof o[k] === 'object') {
              i += 1;
              c[k] = (o[k].constructor === Array) ? [] : {};
              c[k] = _deepCopyObject(o[k]);
          } else {
              c[k] = o[k];
          }
      }
      return c;
  }
}
var parent_3 = {
  name: 'parent_3',
  children: ['foo', 'bar'],
  sayName: function () {
      return this.name;
  }
};
var c3 = deepCopyObject()(parent_3);
c3.name = 'child_3';
c3.children[0] = 'ugly_foo';
//       ,             ,        
//    ,           ,                 ,         
console.log(parent_3.children); // ['foo', 'bar']
方法四:モジュール化の継承
ここまで、私たちが見てきた継承パターンは、父であれ、子であれ、私有属性と方法はなく、すべての属性と方法は対外的に見られ、また改竄されています.このために、もう一つのいい方法を紹介します.モジュールモードは次の通りです.
//    
var parent_4 = function(o) {
  var that = {};
  //        
  var children = ['foo', 'bar'];
  // ...
  var sayName = function() {
    return 'parent sayName: ' + o.name;
  };
  var sayChildren = function () {
    return children;
  };
  //     ,          
  //              that         :
  // 1.           sayName,      sayName()   that.sayName()
  // 2.           ,  that.sayName      ,sayName      ,
  //      sayName      ,  that.sayName      ,         
  that.sayName = sayName;
  that.sayChildren = sayChildren;
  //                     
  return that; 
};
//    
var child_4 = function(o) {
  var that = parent_4(o); //       
  //                     ,                ( this   )
  var uberSayName = that.sayName;
  //                 (       )
  that.uber = parent_4(o);
  //         /  
  var sayName = function() {
    return o.name;
  };
  var sayHi = function() {
    return o.saying;
  };
  //           /  
  that.sayName = sayName;
  that.uberSayName = uberSayName;
  that.sayHi = sayHi;
  return that;
};
//        
var c4 = child_4({
  // name saying            ,        sayName sayHi,          ,
  //   ,               ,              “     ”
  name: 'child_4',
  saying: 'hello world!'
});
console.log(c4.sayName()); // 'child_4'
console.log(c4.uberSayName()); // 'parent sayName: child_4'
console.log(c4.uber.sayName()); // 'parent sayName: child_4'
console.log(c4.sayHi()); // 'hello world!'
結論:モジュール化継承を使用する利点が多いが、最も重要なのはプライベート属性の保護(対象パッケージ)と対外暴露インターフェース(対象間通信)、そして親オブジェクトアプローチにアクセスする能力である.
交流を歓迎します.完.兄弟編——継承:構造関数式