プラグのパッケージから出てきたものをなくして考えます.

5570 ワード

今日は妹の書いたcanvasのプラグインを見て、恥ずかしいです.私より小さいです.ですから、ソースコードを拝見しました.業務上のものは言いませんでした.私も詳しく見ていませんでした.主に下記の部分のコードに引きつけられました.
    _global = (function() {

        return this || (0, eval)('this');
    }());
    
    if (typeof module !== "undefined" && module.exports) {
        module.exports = CanvasStar;
    } else if (typeof define === "function" && define.amd) {
        define(function() {
            return CanvasStar;
        });
    } else {
        !('CanvasStar' in _global) && (_global.CanvasStar = CanvasStar);

    }
よく考えてみたら、ifelse ifの判断の意味が分かりました.
その前に、CanvasStarとは何かを説明します.コードの中にこんな言葉があります.
function CanvasStar() {}
だからこの方法はコードの中でこのcanvasの入り口を実行して、その他のすべての関連している内容はすべて1つの対象として彼の原型の対象に与えました.
更にその二つの判断に戻ると、S 6の前には、commonJSAMDの仕様でコードロードされていますので、現在の環境サポートはcommonjsまたはAMD仕様をサポートしていないという意味です.HTMLファイルで引用するなら、この二つはとりあえずスキップしてください.この二つのところを見ます.
//  1
_global = (function() {

        return this || (0, eval)('this');
}());

//  2    
else{
    !('CanvasStar' in _global) && (_global.CanvasStar = CanvasStar);
}
googleは(0, eval)('this')になりました.このように言っている文章があります.
いずれにしても(0, eval)('this')を呼び出し、返ってくるのはすべてグローバルオブジェクトである.
ですから、問題1はグローバル環境(つまりwindow)を変数に割り当てています.consolethisになりました.ここのthisは大域変数を指すべきです.なぜ後のコードが大域変数を指すのですか?
コードをもう一度読もうとすると、彼女はこのプラグインを書く時に厳格なモードを使っているので、ここのthisunderfinedだけかもしれません.MDNを貼り付けます.厳格なモードでのthisの指向です.
厳密なモードでは、thisを介して関数に伝達される値は、オブジェクトに強制的に変換されません.普通の関数では、thisは常にオブジェクトです.呼び出し時thisは元のオブジェクトです.またはブール値、文字列または数字で関数を呼び出した時に、関数の中にオブジェクトとしてカプセル化されたthisです.undefinedまたはnullを使用して関数thisの代表的なグローバルオブジェクトを呼び出します.このような自動的にオブジェクトに変換するプロセスは、性能上の損失だけでなく、ブラウザで全体のオブジェクトを曝け出すことは、セキュリティ上の危険性となります.グローバルオブジェクトは、いわゆる安全なJavaScript環境にアクセスするために制限されなければならない機能のルートを提供しています.したがって、厳密なモードを開く関数に対しては、指定されたthisは対象としてカプセル化されなくなり、thisが指定されていない場合はundefinedとなります.
長いでしょう.簡単に言えば、厳格なモードでthisに指定値が与えられていないなら、それは未定義です.したがって、このthisは、賦課時にスキップされ、(0, eval)('this')に戻ります.
ここでevalを説明します.私が資料を探している間に、両方の使い方が間接的にeval呼出と直接的なeval呼出ということになりました.この二つの呼出方法の結果は全く違っています.
もう少し多くの資料を見てから、 eval に関するブログを書いています.でも、まずこの中のコンマ操作子について説明してもいいです.
コンマ演算子
これはMDN上の説明です.
コンマ演算子は、その各操作数に対して値を求め(左から右へ)、最後の操作数の値を返します.
いくつかのコードで説明します.
function func1() {
    let a = '         '
    console.log('   ')
    return a
}

function func2() {
    let b = '         '
    console.log('   ')
    return b
}

let c = (func1(), func2())
console.log(c)
ここにはいくつかのevalがありますが、それぞれ何ですか?
今答えを発表します
//console.log  
   
   
         
したがって、定義によれば、evalに対して値を賦与する過程で、左から右にconsolecという2つの方法が順次実行されたが、賦課されたときは最後の値、つまりfunc1に書かれたfunc2だけが返された.
だから私たちはfunc2を見ています.
(0, eval)
ここで返したのもreturnです.これと同じです.
eval('this')
しかしやはり呼び出し方式が違っていますので、最後の結果は違っています.
直ちに関数の公私を実行します.
次に問題2を見れば簡単明瞭になります.彼は大域にevalがあるかどうかを判断する方法です.もし存在しないなら、大域に変数を作成し、内部の方法を彼に与えます.
ここで一つの問題があります.私のように、単独でjsファイルを書いて、それを導入する時は、直接的な調達方法で使っています.なぜこんなに面倒くさいのですか?ですから、ここでもHTMLファイルに直接evalを呼び出してみます.
残念ですが、ブラウザが間違っています.
Uncaught TypeError: CanvasStar is not a constructor
だからここで共有方法と私有方法について話したいです.コードは以下の通りです.
//main.js
(function() {
    let a = '        '

    function sum() {
        console.log(a)
    }
    let log = function() {
        console.log(a)
    }

})()
ファイルから呼び出します.
sum(); // Uncaught ReferenceError: sum is not defined
log(); // Uncaught ReferenceError: log is not defined
CanvasStarの書類をなくして修正します.
//main.js
(function() {
    let a = '        '
    
    log = function() {
        console.log(a)
    }

    function sum() {
        console.log(a)
    }

})()
再起動:

log(); //         
sum(); // Uncaught ReferenceError: sum is not defined
私はjsファイルに関数宣言と関数表現を書いたのは初めてですが、外部では呼び出しができません.2回目は関数表現の変数宣言を削除してから正常にアクセスできます.
この問題の鍵は作用領域にあります.これを確立するとすぐに関数を実行します.作用ドメインチェーンはこうです.
グローバルスコープ
匿名関数
関数のスコープ
変数a
ロゴ関数
sun関数
匿名関数が実行された後、その自身の作用領域は破壊され、彼の前段、すなわちグローバルスコープからはまったく何もアクセスできませんでしたが、関数の割り当てを行う場合、与えられた変数はCanvasStarまたはmain.jsを経て明らかにされませんでした.ここでvarは、グローバルスコープ内に書かれています.外部から直接に呼び出しても大丈夫です.
したがって、letまたはlogによって生成された変数はすべてプライベートであり、関数宣言は必ずプライベートな方法であると結論付けられた.その他は共有変数や方法です.また、共有方法は、作用領域内のプライベート変数にアクセスすることができますが、プライベート変数は外部から直接取得できません.
これはつまりある意味のクローズドです.
別のパッケージ方法
上の内容だけを言ったらつまらないですね.ちょうど私は最近アンダースコアのソースコードを見ています.人のパッケージ方法を見たいです.
規範でその大同小異を判断するなら、言わないが、大域変数の赋価については全く異なる道を歩むべきである.
(function() {
    let root = this;

    ............
    .............
    root._ = _

}.call(this))
このように外部から直接
_.   ;
使えます.
ここで、undersscoreは、この匿名関数を実行する際に、letを使用して、関数のvarを大域変数に指し、ここではcallです.本当に理解できないなら、例を挙げます.
船は海上を航行しています.夜には空が晴れたら、普通のモードを指します.船乗りは天上の星によって方位を判断できます.もし黒い雲が密集していたら、厳格なモードです.道に迷います.ところがちょうど湾岸を回って、有名な灯台を見つけました.再び方向を案内しました.つまり全体です
はっきり言いましたか?