精読JavaScriptモード(7)、ネーミングスペースモード、プライベートメンバーと静的メンバー

17977 ワード

一、前言
惰性は十分で、この2月19日から书いて、今まで引きずって、时间をかけて见たものを整理したくなくて、その他の何事もブログを书くより魅力的で、私は自分を反省します.
ここからは、JSオブジェクト作成モードについての検討ですが、JS言語は簡単で直感的で、モジュール、パッケージ、プライベート属性、静的メンバーなどの文法特性はありません.この章では、ネーミングスペース、依存宣言、モジュールモード、砂箱モードなど、有用なモードについて説明します.これらは、グローバル汚染の問題を軽減するために、コードをよりよく組織するのに役立ちます.
二、ネーミングスペースモード(Namespace Pattern)
ネーミングスペースはグローバル変数の数を減らすことができ、ネーミングの衝突やネーミング接頭辞の乱用を効果的に避けることができ、ネーミングは頭が痛いことだと思います.皆さんはこのような状況があると思います.ネーミングは言葉が貧しいと思います.
JSデフォルト構文ではネーミングスペースはサポートされていませんが、実装されています.ネーミングスペースは実用的です.クラスライブラリ、アプリケーション、プラグインの作成では、グローバルオブジェクトを作成し、すべての機能をこのオブジェクトに追加することができます.大量のグローバル関数、オブジェクトなどをあちこちに明らかにするのではなく、すべての機能をこのオブジェクトに追加することができます.
const MYAPP = {};
MYAPP.Parent = function () {};
MYAPP.number = 4;
MYAPP.modules = {};
MYAPP.modules.data = {};

上記のコードではMYAPPはネーミングスペースオブジェクトであり,名前は任意に取るが,通常は大文字を用いるが,一般的に大文字の変数は定数を表すことに注意する必要がある.
このような表記は命名衝突の可能性が大きく低下ことは明らかであるが、例えばMYAPP.modules.Dataここではコード量が著しく増加し,全体的にファイルのサイズが増加し,次に,あるメソッドの属性を取得する際には,MYAPPから1層ずつ下へ読まなければならず,読み取りが遅い.さらに,このグローバルインスタンスは誤動作によって修正される可能性があるが,これは理論的には定数であり修正すべきではないと述べた.
三、汎用ネーミング空間関数(思想は良いが、鶏肋)
プログラムの複雑さが増すと、ネーミングスペースの作成が保証されにくくなり、既存の変数を誤って変更するのは面倒なので、作成前のチェック動作がより安全になります.
var MYAPP = MYAPP || {}

この知識点の後続の内容は私がスキップしたことを選んで、原書の中の観点はネーミング空間の創建に対して最も良い検査をして、それから1つの共通のネーミング空間の検査関数を提供して、私はテストを経て、提供した関数は永遠に1つの空の対象に戻って、予想の検査効果に達していないことを発見しました;次に、オブジェクトを作成するたびに検出するのは本当に煩雑だと思います.チェック関数をカプセル化しても、呼び出さなければなりません.例えばa.b.c.d.e、私は各層に対してすべて1つの検査をすることができなくて、安全に思想を作るのは良いですが、個人的には鶏の肋骨が多すぎると思います.
四、オブジェクトのプライベート属性と方法
JSはプライベートメンバーの保護、メソッドの構文を専門に提供していません.私たちはグローバルにオブジェクトを作成し、オブジェクトのすべての属性に簡単にアクセスすることができます.
let obj = {
  num:1,
  getNum:function () {
    console.log(this.num);
  }
};
//           
console.log(obj.num);//1
obj.getNum();//1

コンストラクション関数でもそうです.
//     
function GetNum() {
  this.num = 2;
  this.getNum = function () {
    console.log(this.num); 
  }
}
let Num = new GetNum();
console.log(Num.num);//2
Num.getNum();//2

オブジェクトのプロパティをプライベート化するには、閉パッケージを使用します.閉パッケージ内部関数のみが内部変数にアクセスでき、外部は直接アクセスできません.
function GetNum() {
  let num = 3;
  this.getNum = function () {
    console.log(num);
  }
}
let Num = new GetNum();
console.log(Num.num);//undefined
Num.getNum();//3

getNumメソッドを呼び出す以外にnum変数に直接アクセスすることはできませんので、numプロパティにアクセスする特別な権限を持つため、一般的にgetNumメソッドを特権メソッドと呼びます.
特権メソッド権限の問題についてお話しします.文字列ではなくオブジェクトを返すとします.閉包内部に影響するローカル変数を特権メソッドで変更できます.
function BoxInfo() {
  let boxSize = {
    widht:200,
    height:300,
    color:'yellow'
  };
  this.getBox = function () {
    return boxSize;
  }
}
//        box1
let box1 = new BoxInfo(),
  size = box1.getBox();
//    size   
size.color = 'bule';
//    size  ,    size      
size1 = box1.getBox();
console.log(size1)//{widht: 200, height: 300, color: "bule"}
//                  ,     new    
let box2 = new BoxInfo(),
  size2 = box2.getBox();
console.log(size2);//{widht: 200, height: 300, color: "yellow"}

インスタンスを取得して色を変更し、その後にオブジェクトを読み取ると色が変更されていることがわかります.これは肯定的です.結局、オブジェクトの付与値は値そのものではなく値の参照アドレスを与えているだけで、このようなデータを勝手に変更する方法は安全ではありません.この問題に対して、「最低授権原則」を使用して、必要以上に多くのものを与えないでください.
たとえばboxSizeのheightとcolorプロパティにアクセスする必要がある場合、特権メソッドはオブジェクト全体にアクセスできるのではなく、長さと色のプロパティにしかアクセスできません.
this.getBox = function () {
  return {
    height:boxSize.height,
    color:boxSize.color
  }
}

私たちは必要な属性だけを提供して、新しいオブジェクトに組み立てて返して、それからどのように修正しても、私たちは永遠に最初の元のデータを得ることができます.
あるいは、box 1インスタンスを初めて取得したときに、元の属性として使用しなくなり、別のデータが勝手に再生されます.「最低授権原則」という考えはいいと思います.
コンストラクション関数によってプライベートメンバーを作成するほか、オブジェクトの字面量とオートコール関数を組み合わせることで目的を達成することもできます.
(function () {
    var name = "    ";
    myobj = {
        getName : function () {
            return name;
        }
    }
})();
let myName = myobj.getName();
console.log(myName);//    

この実装では,外部からアクセスできない独立した役割ドメインを自己調整関数により作成したが,関数内部のオブジェクトからプライベート属性nameにアクセスできるのは,思想的にはそれほど悪くない.
五、プロトタイプとプライベートメンバー(属性)
コンストラクション関数を使用してプライベート・メンバーを作成するには、コンストラクション関数を使用してインスタンスを作成する場合に発生する弊害があります.コンストラクション関数を呼び出すたびに、プライベート・メンバーが作成されます.
これはnewが1つのコンストラクション関数を作るたびに、空のオブジェクトをステルス的に作成してthisに与え、コンストラクション関数thisの属性方法をコピーして、最終的にthisに戻るためで、これはJSモード3という文章を精読する4番目の知識点で、疑問があれば見てみることができます.
同様に、プライベートメンバーを作成する場合でも、このメンバーが多くの場所で使用される場合は、コンストラクション関数で繰り返し作成され、prototypeに直接追加する必要はありません.
function Mine() {
    let name = "echo";
    this.getName = function () {
        console.log(name);
    };
};
//  age           ,            ,  new    ,   
Mine.prototype = (function () {
    var age = 26;
    return {
        getAge : function () {
            console.log(age);
        }
    };
})();
let me = new Mine();
me.getName();//echo
me.getAge();//26

六、静的メンバー(属性と方法)
1.コンストラクション関数の静的アプローチ
あるメソッドがコンストラクション関数自体のみで使用でき、インスタンスが使用を継承できないことを望む場合は、このメソッドは静的メソッドを使用する必要があります.
JSでは静的メンバーを作成する構文はありませんが、関数を構築して属性を追加する方法で静的メソッドを追加できます.
let Func = function () {};
//  func     
Func.myName = function () {
    console.log('My name is echo');
};
//  func     
Func.prototype.myAge = function () {
    console.log('My age is 26');
};
Func.myName();
let me = new Func();
me.myAge();

上記のコードでは、関数Funcに静的メソッドmyNameとインスタンスメソッドmyAgeを追加しました.
myNameメソッドが静的メソッドである理由は、Func関数が直接呼び出すことができ、オブジェクトを指定して呼び出す必要がなく、インスタンス呼び出しも必要ないからです.しかしmyAgeメソッドではインスタンス呼び出しが必要です.もちろん、関数Fcunは、インスタンスが静的メソッドを直接呼び出すことができないように、インスタンスメソッドを直接呼び出すことはできません.
Func.myAge()//    
me.myName()//    

もちろん、静的メソッドをプロトタイプチェーンに追加することもできます(実際には、ここで理解している静的メソッドは、関数に直接追加する方法であり、一般的にはインスタンスは使用できません)
Func.prototype.myName = Func.myName
let me = new Func();
me.myName()//My name is echo

ただし、違いは、myName関数をFuncで呼び出す場合、関数thisはFunc関数を指しますが、後者のインスタンスで呼び出す場合、thisはインスタンスmeを指します.これは違います.
2.コンストラクション関数の静的属性とプライベート静的属性
静的プロパティの追加は静的メソッドと同様に、コンストラクション関数に直接追加されます.
let Parent = function () {};
//    
Parent.sayAge = function () {
    console.log(this.age);
};
//    
Parent.age = 26;
Parent.sayAge()//26

プライベート静的プロパティとは?2つの大きな特徴があります.1つ目は、同じコンストラクション関数によって作成されたすべてのオブジェクトで共有できることです.第二に、コンストラクション関数の外部へのアクセスは許可されません.
let KissMe = (function() {
  let counter = 0;
  return function() {
    console.log(counter += 1);
  };
})();
console.log(KissMe);
let one = new KissMe();//1
let two = new KissMe();//2
let three = new KissMe();//3

上記のコードでは、変数counterの外部にアクセスできず、3回の呼び出しで得られたインスタンスがcounterを共有する構造関数を定義しました.2回目の呼び出しでcounterは0ではなく1になったため、counterはプライベートな静的属性と言えます.
コードをよく見ると、実は構造関数が1つの自己調整関数に包まれており、外層自己調整関数を除いて見ると、この実現の本質はグローバル変数counterとこの変数を使用する関数である.
let counter = 0;
let KissMe = function() {
  console.log((counter += 1));
};
console.log(KissMe);
let one = KissMe(); //1
let two = KissMe(); //2
let three = KissMe(); //3

発見されたかどうかは,1つの構造関数がnewされたことを何回知りたいか,あるいはこの例が構造関数の何人目の子供であるかを知りたいと仮定すると,この簡単な実装で回数を計算できる.(本当に使えるかも)
上の自己調整関数の例は構造関数と言っても少し強引ですが、結局私たちがnew KissMeの時に関数はすでに実行済みで、インスタンス呼び出し方法を通過する機会がないので、コードを変更しました.結果は同じですが、構造関数モードに似ています.
さらに、プライベートメンバーとプライベート静的メンバーの違いは、プライベートメンバーがインスタンスごとに新しいものであり、共有されないことであり、プライベート静的メンバーの2番目のインスタンスが1番目のインスタンス呼び出しの影響を受けていることが明らかである.
let KissMe = (function() {
  let counter = 0,
    getNum = function() {
      counter += 1;
    };
  getNum.prototype.getLastId = function() {
    console.log(counter);
  };
  return getNum;
})();

let one = new KissMe();
one.getLastId();//1
let two = new KissMe();
one.getLastId();//2
let three = new KissMe();
one.getLastId();//3

上記の例では、静的プロパティ(公有または私有)はインスタンスに関係のないメソッドまたはデータを含むことができ、インスタンスを作成する場合、これらの私有プロパティは繰り返し作成されませんが、インスタンスは使用できます.プロトタイプチェーン継承に似ていると思いますが、プロトタイプチェーン追加方法とは異なり、最終実行時にthisが異なることを指します.
七、面白いオブジェクトチェーン呼び出しモード
1つのオブジェクト上の複数のメソッドを連続的に呼び出す必要があり、操作されたデータが関連付けられていると仮定すると、呼び出すたびにthisを関数呼び出しの戻り値として直接使用することができ、呼び出すたびに戻り値が次回の呼び出し関数パラメータとして煩雑になることを回避できます.
let obj = {
  value: 1,
  plus: function(a) {
    this.value += a;
    return this;
  },
  reduce: function() {
    this.value -= 1;
    return this;
  },
  multiply: function() {
    this.value *= 2;
    console.log(this.value);
  }
};
obj.plus(3).reduce().multiply();//6

これはpromiseチェーン構造のような書き方で、promiseの実行のたびに新しいpromiseオブジェクトが返されます.ここではthisを返すたびに、操作がすべてthisなので、これは多くありません.
チェーン呼び出しモードを使用すると、コード量を大幅に節約できますが、実際には文のように読むと、関数間の呼び出しを関連付けやすくなります.実はこのパターンはよく見られます.例えば、私たちがよく使うJQがDOMを取得する書き方です.
document.getElementById("#echo").appendChild(new node);

それではここまで、第5章の内容は大体见终わって、実はブログの中で私は比较的に多いものを省略して、例えば砂箱のモード、モジュールのモードなど、见る前に私はやはり期待して、しかし実际に読む中で、このいくつかの知识の点の収货はきわめて少なくて、一方で例が分かりにくくておよび间违いが存在して、実は私の个人の境界はまだあまり高くないかもしれなくて、见てもすぐに実际の开発の中で実践することができなくて、だから、私個人が意味を持っているものをもっと記録しました.たとえ概念をもっと知っていても.
寝ましょう.気を楽にします.