JSコード多重モード

7172 ワード

多重化は非常に重要な生活技能です.生命は限られているので、無意味な反復は生命を浪費することに等しいです.プログラム開発者として、コードの多重化は能力であり、積極的な生活に対する態度でもある.では、JSはコード多重化にはどのような方法がありますか?
………………
作成モード
コンストラクタと一般関数の唯一の違いは、呼び出し方式が異なることであり、どの関数も構造関数としてnewキーワードで呼び出すことができる(コンストラクタ=new+普通関数).
function Parent() {
  this.name = "jim";
  this.say = function() {
    console.log(this.name);
  };
  console.log(this.name);
}
Parent(); //    jim
console.log(Parent); //    Parent (){/*    -  */}

var child1 = new Parent(); //    jim        child1   (    )
var child2 = new Parent(); //    jim        child2   (    )

console.log(child1); //    Parent {name: "jim", say: ƒ ()}
console.log(child1.say); //    ƒ () {/*    -  */}

child1.say(); //    jim
child2.say(); //    jim

console.log(child1.name); //    jim (child1     Parent name)
console.log(child2.name); //    jim (child2     Parent name)

child1.name = "tom1"; //    child   name   
child2.name = "tom2"; //    child   name   

child1.say(); //    tom1(   child       name   )
child2.say(); //    tom2(   child       name   )
console.log(child1.name); //    tom1(   child       name   )
console.log(child2.name); //    tom2(   child       name   )

delete child1.name; //    child1   name   
delete child2.name; //    child2   name   

console.log(child1.name); //    undefined(   child1      name      )
console.log(child2.name); //    undefined(   child2      name      )

Parent(); //    jim (                      )
短所:親オブジェクトの属性を多重できない方法で、子オブジェクトの数が多くなり、newを繰り返して親オブジェクトを作成します.
プロトタイプ
すべての引用タイプはObjectであり、つまり引用タイプの原型はObjectであり、彼らは継承の関係であることを知っています.また、プロトタイプの属性はカスタマイズできます.
function fn() {
  this.keyThis = ["fnThisValue"];
}
// name: "fn" prototype: {constructor: fn()} __proto__: Object
//      fn
//    prototype       ,      constructor       
//    __proto__    Object(   __proto__          ,      )
//   fn    , this     window ,    keyThis        

//     JS         ,              
fn.prototype.keyProto = ["fnProtoValue"];
console.log(fn.prototype);
//    {keyProto: ["fnProtoValue"], constructor: fn(),__proto__: Object}

var foo = new fn(); // fn()   , this  window,key1     
console.log(foo);
//   
// fn{
//    keyThis:["fooThisValue"],
//    __proto__:{ keyProto: ["fnProtoValue"], constructor: fn(), __proto__: Object}
// }
// foo          (          ),      __proto__   fn    
//        __proto__:{__proto__:{···}}

console.log(foo.keyThis); //    ["fooThisValue"]
console.log(foo.keyProto); //    ["fnProtoValue"]

foo.keyThis.push("fooThis");
foo.keyProto.push("fooProto");

console.log(foo);
//   
// fn{
//    keyThis:["fooThisValue", "fooThis"],
//    __proto__:{ keyProto: ["fnProtoValue", "fooThis"], constructor: fn(), __proto__: Object}
// }
// foo            ,          (      ),          this    

console.log(fn.prototype);
//   { keyProto: ["fnProtoValue", "fooThis"], constructor: fn(), __proto__: Object}
短所:親オブジェクトの属性を多重化する方法ですが、子オブジェクトの数が多くなり、newを繰り返して親オブジェクトを作成します.
借用モード
JSベースデータタイプのオペレーティングシリーズ(4)関数において,call,appy,bindの関数的スコープ借用動作を紹介したが,これもコード多重の良い方法である.
function Parent() {
  this.keyThis = ["fnThisValue"];
}
Parent.prototype.keyProto = ["fnProtoValue"];
function Child() {
  Parent.call(this);
  console.log(this.keyThis); //    ["fnThisValue"]
  console.log(this.keyProto); //    undefined
}
Child();
//           this           。

var jim = new Child();
console.log(jim.keyThis); //    ["fnThisValue"]
console.log(jim.keyProto); //    undefined
//           this           。
プロキシモード
function inherit(parent, child) {
  var F = function() {};
  F.prototype = parent.prototype;
  child.prototype = new F();
  child.prototype.constructor = child;
}

function Parent() {
  this.keyThis = ["fnThisValue"];
}
Parent.prototype.keyProto = ["fnProtoValue"];

function Child() {}
inherit(Parent, Child);

var jim = new Child();
console.log(jim.keyThis); //    undefined
console.log(jim.keyProto); //    ["fnProtoValue"]
短所:プロトタイプだけを代理しました.
標準モード
ES 5では、プロトタイプ構造継承(シンタックス糖)を実現するためのObject.create()方法が提供される.Object.create()方法で新たに作成されたオブジェクトを作成し、既存のオブジェクトを使用して新規に作成されたオブジェクトを提供する__proto__.
文法:Object.creat.
第二のオプションパラメータはnullまたはオブジェクトで、新規作成オブジェクトに追加されたカスタムエニュメレート・属性は、Object.defineProperties()の第二のパラメータに対応します.
function Parent() {}
Parent.prototype.keyProto = ["fnProtoValue"];

var jim = Object.create(Parent, {
  key: { value: "val" }
});

console.log(jim); //    Function {key: "val",__proto__: Parent()}
jim.hasOwnProperty("key");


var Fn = {
    key:"value"
}
Object.create(Fn)
// {__proto__:{ key:"value"}}
クローンモード
属性をコピーすることで継承を実現します.
浅いクローン
単純オブジェクト、単層クローン
function extend(parent, child) {
  var i;
  child = child || {};
  for (i in parent) {
    if (parent.hasOwnProperty(i)) {
      child[i] = parent[i]; //       ,      
    }
  }
  return child;
}

var Parent = {
    key:"value",
    arr:[1,2,3,4],
    obj:{
        key:"value",
        arr:[1,2,3,4],
    }
}
var kid = extend(Parent)
kid.arr.push(4);
console.log(Parent.arr)  //    [1,2,3,4,4]
クローン
複雑なオブジェクト、再帰的にクローン
function extendDeep(parent, child) {
  var i,
    toStr = Object.prototype.toString,
    astr = "[object Array]";
  child = child || {};
  for (i in parent) {
    if (parent.hasOwnProperty(i)) {
      if (typeof parent[i] === "object") {
        child[i] = toStr.call(parent[i]) === astr ? [] : {};
        arguments.callee(parent[i], child[i]);
      } else {
        child[i] = parent[i];
      }
    }
  }
  return child;
}
var Parent = {
    key:"value",
    arr:[1,2,3,4],
    obj:{
        key:"value",
        arr:[1,2,3,4],
    }
}
var kid = extendDeep(Parent)
kid.arr.push(4);
console.log(Parent.arr)  //    [1,2,3,4]
短所:対象は対象で、関数ではなく、もちろん対象はこれが一番いいです.
締め括りをつける
以上より、this属性を継承することができ、prototype属性を継承することができる方法が欲しい.thisのプロパティを継承するのに最も良いのは、借用モードであり、prototypeのプロパティを継承するのに最も良いのはObject.create()標準モードである.
function parent() {
  this.money = 1000;
}
parent.prototype.say = function(money) {
  console.log("I have " + (this.money + money));
}

function inherit(parent,childParams){
    function Child() {
        parent.call(this);      //       this   
    }
    childParams = childParams || {}; //       
    Child.prototype = Object.create(parent.prototype,childParams);
    // parent.prototype       parent Prototype
    // Object.create(parent.prototype)
    //    {__proto__:{ say:ƒ (money),constructor:ƒ parent(), __proto__:Object}}
    Child.prototype.constructor = Child; //                
    return new Child()
}

var jim = inherit(parent);
var tom = inherit(parent,{key:{value:500}});
jim.say(100);   //   I have 1100
tom.say(500);   //   I have 1100
tom.key         //   500