JavaScriptのスコープの詳しい説明

阿神
リリース: 2017-03-04 14:44:52
オリジナル
1171 人が閲覧しました

はじめに

JavaScript はフルスタック言語で、特に 2016 年は JavaScript が世界を席巻するとよく聞きます。Vue.js を知っていれば仕事が見つかるという噂もあります。 、当時は、iOS の TableView を知っていれば仕事を見つけることができました (tableView は Android の ListView に相当しますが、現在は基本的に RecyclerView が使用されます)

2016 年に人気のあるフロントエンド テクノロジは、基本的に JavaScript に関連しています。モバイル クロスプラットフォームの Facebook 製品である React Native と Alibaba の Weex、ホット リペア テクノロジの JSPath、およびバックエンドの Node.js (私がとても気に入っているテクノロジ スタック) については、昨夜 gibhub に行ってその番号を確認しました。 Vue のスターの数は jQuery のスターの数を上回りましたが、星の数だけでは何も証明されませんが、少なくともフロントエンドの考え方が以前のドキュメント操作からデータ駆動型開発に変化したことがわかりました (興味があれば、 Android、iOS、および Vue を組み合わせて、このアイデアを小さなデモで実証できます。Change)、一部の企業は、Ele.me が作成した Element を EasyUI の代わりに使用しようとさえしました (バックエンドをやったことがある学生は EasyUI が知っているはずです)。本当にAV品質...)

JSテクノロジーは次々と登場しており、以前非常に人気のある記事がありました。2016年にJSを学ぶのはどのようなものかという記事は、多くの人々を怖がらせました。新しいテクノロジーですが、ネイティブ JS は無視されていたので、いくつかの基本的な JS の問題を伝えておきたいと思いました。セクシーな JS の問題、みんなとコミュニケーションを取りましょう


JavaScript のスコープ

以下はシンプルな質問:

<script>
    var str1 = "hello";
    var str2 = "world";

    function t1() {
        console.log(str1);
        console.log(str2);

        var str2 = "toby";
        console.log(str2);
    }

    //这里会输出什么?
    t1();

</script>
ログイン後にコピー

これは非常にシンプルな JS スコープの問題ですが、シンプルという言葉が強調されるほど、人々は警戒を緩めやすくなり、考えずに答えてしまう生徒もいます

● こんにちは。

●world

●toby

ですが、結果は

●hello

●未定義

●toby

それで、これは奇妙です、なぜ未定義があるのですか?変数の検索は近接性の原則に従うため、js は最初に関数内を検索しますが、それが見つからない場合にのみ外部で検索され、関数内に str2 がありますが、str2 は定義されていないことを理解する必要があります。 console.log(str2) を実行すると、未定義が表示されます。まだ理由を知る必要があるので、さらにいくつかの例を見てみましょう

例 1

<script>
    function t(userName) {
        console.log(userName);//这里输出什么?

        function userName() {
            console.log(&#39;tom&#39;);
        }
    }
    t(&#39;toby&#39;);
</script>
ログイン後にコピー

この出力結果は上記とは異なるようです? . 高校の数学に戻るようなものです。この時点では、toby だと思う人もいると思いますが、実際の出力は

function userName() {
    console.log(&#39;tom&#39;);
}
ログイン後にコピー
です。 、この種のスコープの問題は、「一連の式」を通じて取得できます。この式は、JS 字句解析におけるものです。JS の関数を実行する前に実行する必要があるタスクの 1 つが字句解析です。そのため、正確には何が必要になります。 ? パラメータを分析し、変数宣言を分析し、関数宣言を分析します。その後、この質問を使用して式を設定します t('toby') が実行されると、2 つのフェーズが始まります。実行フェーズに移行します。
分析フェーズ:

● 関数が実行されると、アクティブ オブジェクト (以下、AO オブジェクトと呼びます) が生成され、関数スコープ内で見つかるすべての変数がオンになります。 AO. このときのコードは、 t.AO = {}

と表します。 ● 解析パラメータ:パラメータを受け取り、パラメータ名を属性として使用し、パラメータ パラメータがないため、その値が属性値になります。をコードで表現します: t.AO = {userName : toby}

● var ステートメントの分析: t 関数内に var ステートメントがないのでスキップします

● function ステートメントの分析: この Function 宣言には特性があります。 AO には関数名と同じ名前の属性があり、この関数によって上書きされます。関数も JS フィールドの変数の一種であるため、コードでは次のように表現されます。 t.AO = { userName: function userName() {console.log('tom');}}

実行フェーズ:

t('toby')を実行するとき、console.log(userName)が実行されると、tが呼び出されます。 AO.userName なので、最終的な出力結果は function userName() {console.log('tom');}

例 2

<script>
    function t(userName) {
        console.log(userName);//这里输出什么?

        var userName = function () {
            console.log(&#39;tom&#39;);
        }
    }
    t(&#39;toby&#39;);
</script>
ログイン後にコピー

ここでの出力は上記と同じと思われます。例が違っていて、また混乱していませんか? トラブルを恐れず、毅然として公式に従い、プロセスをもう一度実行してください (上記の例はより詳細に書かれており、以下の分析は単純に書かれています)

分析の前に、まずこの 2 つを理解する必要があります。 2 つの概念があり、1 つは関数宣言と呼ばれ、もう 1 つは関数式と呼ばれます

//这个叫函数声明
function userName() {
    console.log(&#39;tom&#39;);
}

//这个叫函数表达式
var userName = function () {
    console.log('tom');
}
ログイン後にコピー

分析ステージ:

● AO オブジェクトを作成します、t.AO = {}

● 分析パラメータ: t。 AO = {ユーザー名 : toby}

● 分析var声明: 在AO上,形成一个属性,以var的变量名为属性名,值为undefined,(因为是先分析,后执行,这只是词法分析阶段,并不是执行阶段,分析阶段值都是undefined,如果执行阶段有赋值操作,那值会按照正常赋值改变),也就是说代码应该表示为:t.AO = {userName : undefined},但是还有另外一个原则,那就是如果AO有已经有同名属性,则不影响(也就是什么事都不做),由于分析参数时,AO上已经有userName这个属性了,所以按照这个原则,此时什么事都不做,也就是说,此时按照分析参数时的结果t.AO = {userName : toby}

● 分析函数声明: 此时没有函数声明,略过

执行阶段:

调用t.AO.userName,所以,最后的输出结果是toby

例子3

<script>
    t();
    t2();

    function t() {
        console.log(&#39;toby&#39;);//这里会输出什么?
    }

    var t2 = function () {
        console.log(&#39;hello toby&#39;);//这里会输出什么?
    };
</script>
ログイン後にコピー

那么我们再来看一个例子,这下彻底回到高中时代,做了两个例子好像感觉掌握了,结果考试你给来看这个?

答案是,t()输出为toby,t2()则会报错.这又是为什么?

● t()可以调用是因为在词法分析的过程,就已经完成了t函数的分析,所以可以调用

● t2()不能调用是因为在词法分析的阶段,分析到有一个t2声明,在AO上只是形成了一个属性,但是值为undefined

例子4

<script>
    function t(userName) {
        console.log(userName);//这里输出什么?
        function userName() {
            console.log(userName);//这里输出什么?
        }
        userName();
    }
    t(&#39;toby&#39;);
</script>
ログイン後にコピー

函数里面套函数,这次竟然又和前面不一样了...这次我不说答案了,直接先套公式走一波

t('toby')的分析和执行阶段

分析阶段:

● 创建AO对象,t.AO = {}

● 分析参数: t.AO = {userName : toby}

● 分析var声明: 有同名属性,不做任何事,还是t.AO = {userName : toby}

● 分析函数声明: 有同名属性,覆盖: t.AO = {userName : function userName() {console.log(userName);}}

执行阶段: t.AO.userName 输出为function userName() {console.log(userName);}}

userName()的分析和执行阶段

这里也要搞清楚两个概念

//执行userName()分析的是
function () {
  console.log(userName);
};

//而不是
var userName = function () {
    console.log(userName);
};
ログイン後にコピー

分析阶段:

● 创建AO对象,userName.AO = {}

● 分析参数: 无,略过

● 分析var声明: 无,略过

● 分析函数声明: 无,略过

执行阶段: 因为此时userName.AO = {}是个空对象,无法执行userName.AO.userName,所以会向上一层找,所以输出t.AO.userName的结果,也就是function userName() {console.log(userName);}}

例子5

<script>
    function t(userName) {
        console.log(userName);//这里输出什么?
        var userName = function () {
            console.log(userName);//这里输出什么?
        }
        userName();
    }
    t(&#39;toby&#39;);
</script>
ログイン後にコピー

好吧,我保证这个是最后一道...这个输出结果是什么呢?我们只要坚定公式没问题,就一定能得出结果,那么再套公式走一波

t('toby')的分析和执行阶段

分析阶段:

● 创建AO对象,t.AO = {}

● 分析参数: t.AO = {userName : toby}

● 分析var声明: 有同名属性,不做任何事,还是t.AO = {userName : toby}

● 分析函数声明: 无,略过

执行阶段: 执行console.log(userName);时调用t.AO.userName 输出为toby,执行完后,代码继续往下执行,那么就到了进行var的赋值操作(var的分析和执行的区别看例子2中我有解释),此时t.AO = {userName : function() {console.log(userName);}},代码继续往下执行,接着就执行到了userName()

userName()的分析和执行阶段

分析阶段:

● 创建AO对象,userName.AO = {}

● 分析参数: 无,略过

● 分析var声明: 无,略过

● 分析函数声明: 无,略过

执行阶段: 按照例子4我们知道userName.AO是个空对象,所以会往上调用t.AO.userName,所以输出为:function () {console.log(userName);}


总结

JavaScript作用域会先在自己的AO上找,找不到就到父函数的AO上找,再找不到再找上一层的AO,直到找到window.这样就形成一条链,这条AO链就是JavaScript中的作用域链.

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!