3つの問題はJavaScript関数、変数、対象、作用域に対する理解度を考察します.

4324 ワード


試し牛刀
この文章は一つの問題から始まります.後は徐々にこの問題をもとに展開します.まず下記のコードを実行してから出力されるものは何かを考えてみます.
getAge()
var getAge = function(){
    console.log(18);
}
function getAge(){
    console.log(20);
}
getAge()
この問題は二つの知識点を試験しました.一つはJavaScriptにおける変数の昇格です.もう一つは関数の定義は関数宣言と関数式の2種類があります.
変数アップとは?
  • 関数および変数の宣言は、スコープの最上部に引き上げられます.
  • 変数は、使用後に宣言することができます.すなわち、変数は先に再宣言を使用することができます.
  • 関数宣言
    fun()
    function fun(){
        console.log('    ');
    }
    fun()
    上記は関数宣言の方式であり、変数アップ機構によって、ここでのfun()が一番上に引き上げられるので、ここでの結果は明らかである.
    /*  */
    fun()    //    
    function fun(){
        console.log('    ');
    }
    fun()    //    
    この例を通して、関数宣言はJS解析時に関数の向上を行うので、同じスコープ内では関数がどこで宣言を定義しても、この関数は呼び出されます.
    関数式
    fun()
    var fun = function(){
        console.log('     ');
    }
    表式宣言は、関数を変数に割り当てます.この変数はもちろん、一番前に引き上げられますが、ここにはピットがあります.変数の昇格は変数を一番前に上げただけですが、割当はJS運転時に行います.出力結果を見て,funは関数ではないことを示した.
    fun()  //Uncaught TypeError: fun is not a function
    var fun = function(){
        console.log('     ');
    }
    funを後ろに置いてみます.
    var fun = function(){
        console.log('     ');
    }
    fun()   //     
    fun関数は正常に実行できます.この時点で既に割り当てられています.
    上の内容を理解してから、初めの問題を振り返ってみます.答えは次の通りです.
    getAge()   // 20
    var getAge = function(){
        console.log(18);
    }
    function getAge(){
        console.log(20);
    }
    getAge()   //18
    関数オブジェクト
    JavaScriptでは関数も対象となり、自分の構造関数を持ち、プロトタイプチェーンもあります.同じ思考問題から始まります.
    function Person(){
        getAge = function(){
            console.log(17);
        }
        this.getAge = function(){
            console.log(18);
        }
    }
    Person.getAge = function(){
        console.log(19);
    }
    Person.prototype.getAge = function(){
        console.log(20);
    }
    Person.getAge()
    new Person().getAge()
    この問題は主に対象の私有属性/方法、公有属性/方法、静的属性/方法を考察します.
  • 共有属性/方法は、実装されていなければ使用できません.つまりnew操作です.
  • 共有方法は、プライベート方法の静的方法を起動することができない.
  • プライベート属性およびプライベート方法は、外部にアクセスできません.
  • 静的属性および静的方法は、実用化なしにアクセスできる.
  • Person.getAge() ここではPersonを実装していないので、呼び出しPersonの静的な方法です.
    new Person().getAge() このステップは、まずPersonを実装し、インスタンスのgetAge()方法を呼び出した.本質はこのような順序(new Person()getAge()です.でも今は問題があります.Personさん. 構造関数とプロトタイプ鎖の両方にgetAge()法がある.この場合はプロトタイプではなくコンストラクタ内の公有法をデフォルトで使用します.
    function Person(){
        function getAge(){   //    
            console.log(17);
        }
        this.getAge = function(){   //    
            console.log(18);
        }
    }
    Person.getAge = function(){   //    
        console.log(19);
    }
    Person.prototype.getAge = function(){    //    
        console.log(20);
    }
    Person.getAge()    //19
    new Person().getAge()    //18
    thisの指向
    この問題は前の問題に対して難しいです.ここでは主にthisと作用域に対する考察です.
    function Person(){
        this.getAge = function(){
            console.log(18);
        }
        getAge = function(){
            console.log(19);
        }
        return this
    }
    var getAge = function(){
        console.log(20);
    }
    ​
    getAge()
    Person().getAge()
    new Person().getAge()
    getAge()
    第一問:getAge() ,これは比較的簡単です.説明できるものはありません.ただgetAge関数を実行します.
    第二の質問:Person().getAge()は最初にPerson()関数を実行し、その後Person関数から返されたオブジェクトのgetAge属性関数を呼び出します.その中のgetAge=function(){consolie.log(19)}は、現在の作用領域ではgetAgeが宣言されていないため、上位の作用領域に変数getAgeを探しています.外部ではvar getAge=function(){consolie.log(20)}変数が向上していますので、ここではグローバル変数getAgeが修正されたのに相当します.関数から返されたthisはここではwindowを指します.ここではPerson関数を実行しますが、実用化されていません.だからPerson().getAge()はwindowでのgetAgeメソッドの呼び出しに相当し、最終的な出力結果は19です.
    第三の質問:第二の質問とは違って、ここでPersonを実例化したので、ここで戻ってきたthisは戻ってきた例を指し、次いでこの実例の公有方法、つまりthis.getAgeを呼び出します.
    第四問:この質問は第一問とほぼ同じように見えますが、第二問の分析により、グローバル変数getAgeは第二問で修正されたので、ここの出力は19です.
    コンストラクタの戻り値
    従来の言語では、コンストラクタは値を返していません.実際の戻り値はこのコンストラクターのものです.
    JavaScriptの中の構造関数は戻り値があってもいいし、なくてもいいです.ここでは3つの状況に分けられます.
  • は、戻り値がない場合には、例示的なオブジェクトを返します.
  • function Person(name){
        this.name = name
    }
    console.log(new Person('bbb').name);   //bbb
  • には戻り値がありますが、戻り値がない場合と同じで、String、Number、Boolean、Null、Udefinedなどの値の種類が返されます.
  • function Person(name){
        this.name = name
        name = 'aaa'
        return name
    }
    console.log(new Person('bbb').name);   //bbb
  • は、戻り値があり、戻り値は参照タイプである.では、実際に戻ったのが戻り値です.
  • function Person(name){
        this.name = name
        name = 'aaa'
        return name
    }
    console.log(new Person('bbb').name);   //bbb