成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

js作用域與命名空間

antyiwei / 2360人閱讀

摘要:全局變量函數(shù)內(nèi)的局部作用域和是函數(shù)內(nèi)的局部變量,而對(duì)的賦值將會(huì)覆蓋全局作用域內(nèi)的同名變量。命名空間只有一個(gè)全局作用域?qū)е碌某R?jiàn)錯(cuò)誤是命名沖突。另外兩種方式結(jié)論推薦使用匿名包裝器譯者注也就是自執(zhí)行的匿名函數(shù)來(lái)創(chuàng)建命名空間。

盡管 JavaScript 支持一對(duì)花括號(hào)創(chuàng)建的代碼段,但是并不支持塊級(jí)作用域;
而僅僅支持 函數(shù)作用域。

function test() { // 一個(gè)作用域
    for(var i = 0; i < 10; i++) { // 不是一個(gè)作用域
        // count
    }
    console.log(i); // 10
}
  

注意: 如果不是在賦值語(yǔ)句中,而是在 return 表達(dá)式或者函數(shù)參數(shù)中,{...} 將會(huì)作為代碼段解析,
而不是作為對(duì)象的字面語(yǔ)法解析。如果考慮到 自動(dòng)分號(hào)插入,這可能會(huì)導(dǎo)致一些不易察覺(jué)的錯(cuò)誤。

譯者注:如果 return 對(duì)象的左括號(hào)和 return 不在一行上就會(huì)出錯(cuò)。

// 譯者注:下面輸出 undefined
function add(a, b) {
    return 
        a + b;
}
console.log(add(1, 2));

JavaScript 中沒(méi)有顯式的命名空間定義,這就意味著所有對(duì)象都定義在一個(gè)全局共享的命名空間下面。

每次引用一個(gè)變量,JavaScript 會(huì)向上遍歷整個(gè)作用域直到找到這個(gè)變量為止。
如果到達(dá)全局作用域但是這個(gè)變量仍未找到,則會(huì)拋出 ReferenceError 異常。

隱式的全局變量
// 腳本 A
foo = "42";

// 腳本 B
var foo = "42"

上面兩段腳本效果不同。腳本 A 在全局作用域內(nèi)定義了變量 foo,而腳本 B 在當(dāng)前作用域內(nèi)定義變量 foo。

再次強(qiáng)調(diào),上面的效果完全不同,不使用 var 聲明變量將會(huì)導(dǎo)致隱式的全局變量產(chǎn)生。

// 全局作用域
var foo = 42;
function test() {
    // 局部作用域
    foo = 21;
}
test();
foo; // 21

在函數(shù) test 內(nèi)不使用 var 關(guān)鍵字聲明 foo 變量將會(huì)覆蓋外部的同名變量。
起初這看起來(lái)并不是大問(wèn)題,但是當(dāng)有成千上萬(wàn)行代碼時(shí),不使用 var 聲明變量將會(huì)帶來(lái)難以跟蹤的 BUG。

// 全局作用域
var items = [/* 數(shù)組 */];
for(var i = 0; i < 10; i++) {
    subLoop();
}

function subLoop() {
    // subLoop 函數(shù)作用域
    for(i = 0; i < 10; i++) { // 沒(méi)有使用 var 聲明變量
        // 干活
    }
}

外部循環(huán)在第一次調(diào)用 subLoop 之后就會(huì)終止,因?yàn)?subLoop 覆蓋了全局變量 i
在第二個(gè) for 循環(huán)中使用 var 聲明變量可以避免這種錯(cuò)誤。
聲明變量時(shí)絕對(duì)不要遺漏 var 關(guān)鍵字,除非這就是期望的影響外部作用域的行為。

局部變量

JavaScript 中局部變量只可能通過(guò)兩種方式聲明,一個(gè)是作為函數(shù)參數(shù),另一個(gè)是通過(guò) var 關(guān)鍵字聲明。

// 全局變量
var foo = 1;
var bar = 2;
var i = 2;

function test(i) {
    // 函數(shù) test 內(nèi)的局部作用域
    i = 5;

    var foo = 3;
    bar = 4;
}
test(10);

fooi 是函數(shù) test 內(nèi)的局部變量,而對(duì) bar 的賦值將會(huì)覆蓋全局作用域內(nèi)的同名變量。

變量聲明提升(Hoisting)

JavaScript 會(huì)提升變量聲明。這意味著 var 表達(dá)式和 function 聲明都將會(huì)被提升到當(dāng)前作用域的頂部。

bar();
var bar = function() {};
var someValue = 42;

test();
function test(data) {
    if (false) {
        goo = 1;

    } else {
        var goo = 2;
    }
    for(var i = 0; i < 100; i++) {
        var e = data[i];
    }
}

上面代碼在運(yùn)行之前將會(huì)被轉(zhuǎn)化。JavaScript 將會(huì)把 var 表達(dá)式和 function 聲明提升到當(dāng)前作用域的頂部。

// var 表達(dá)式被移動(dòng)到這里
var bar, someValue; // 缺省值是 "undefined"

// 函數(shù)聲明也會(huì)提升
function test(data) {
    var goo, i, e; // 沒(méi)有塊級(jí)作用域,這些變量被移動(dòng)到函數(shù)頂部
    if (false) {
        goo = 1;

    } else {
        goo = 2;
    }
    for(i = 0; i < 100; i++) {
        e = data[i];
    }
}

bar(); // 出錯(cuò):TypeError,因?yàn)?bar 依然是 "undefined"
someValue = 42; // 賦值語(yǔ)句不會(huì)被提升規(guī)則(hoisting)影響
bar = function() {};

test();

沒(méi)有塊級(jí)作用域不僅導(dǎo)致 var 表達(dá)式被從循環(huán)內(nèi)移到外部,而且使一些 if 表達(dá)式更難看懂。

在原來(lái)代碼中,if 表達(dá)式看起來(lái)修改了全部變量 goo,實(shí)際上在提升規(guī)則被應(yīng)用后,卻是在修改局部變量。

如果沒(méi)有提升規(guī)則(hoisting)的知識(shí),下面的代碼看起來(lái)會(huì)拋出異常 ReferenceError。

// 檢查 SomeImportantThing 是否已經(jīng)被初始化
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}

實(shí)際上,上面的代碼正常運(yùn)行,因?yàn)?var 表達(dá)式會(huì)被提升到全局作用域的頂部。

var SomeImportantThing;

// 其它一些代碼,可能會(huì)初始化 SomeImportantThing,也可能不會(huì)

// 檢查是否已經(jīng)被初始化
if (!SomeImportantThing) {
    SomeImportantThing = {};
}

譯者注:在 Nettuts+ 網(wǎng)站有一篇介紹 hoisting 的文章,其中的代碼很有啟發(fā)性。

// 譯者注:來(lái)自 Nettuts+ 的一段代碼,生動(dòng)的闡述了 JavaScript 中變量聲明提升規(guī)則
var myvar = "my value";  

(function() {  
    alert(myvar); // undefined  
    var myvar = "local value";  
})();  
名稱解析順序

JavaScript 中的所有作用域,包括全局作用域,都有一個(gè)特別的名稱 this 指向當(dāng)前對(duì)象。

函數(shù)作用域內(nèi)也有默認(rèn)的變量 arguments,其中包含了傳遞到函數(shù)中的參數(shù)。

比如,當(dāng)訪問(wèn)函數(shù)內(nèi)的 foo 變量時(shí),JavaScript 會(huì)按照下面順序查找:

當(dāng)前作用域內(nèi)是否有 var foo 的定義。

函數(shù)形式參數(shù)是否有使用 foo 名稱的。

函數(shù)自身是否叫做 foo。

回溯到上一級(jí)作用域,然后從 #1 重新開(kāi)始。

  

注意: 自定義 arguments 參數(shù)將會(huì)阻止原生的 arguments 對(duì)象的創(chuàng)建。

命名空間

只有一個(gè)全局作用域?qū)е碌某R?jiàn)錯(cuò)誤是命名沖突。在 JavaScript中,這可以通過(guò) 匿名包裝器 輕松解決。

(function() {
    // 函數(shù)創(chuàng)建一個(gè)命名空間

    window.foo = function() {
        // 對(duì)外公開(kāi)的函數(shù),創(chuàng)建了閉包
    };

})(); // 立即執(zhí)行此匿名函數(shù)

匿名函數(shù)被認(rèn)為是 表達(dá)式;因此為了可調(diào)用性,它們首先會(huì)被執(zhí)行。

( // 小括號(hào)內(nèi)的函數(shù)首先被執(zhí)行
function() {}
) // 并且返回函數(shù)對(duì)象
() // 調(diào)用上面的執(zhí)行結(jié)果,也就是函數(shù)對(duì)象

有一些其他的調(diào)用函數(shù)表達(dá)式的方法,比如下面的兩種方式語(yǔ)法不同,但是效果一模一樣。

// 另外兩種方式
+function(){}();
(function(){}());
結(jié)論

推薦使用匿名包裝器譯者注:也就是自執(zhí)行的匿名函數(shù))來(lái)創(chuàng)建命名空間。這樣不僅可以防止命名沖突,
而且有利于程序的模塊化。

另外,使用全局變量被認(rèn)為是不好的習(xí)慣。這樣的代碼傾向于產(chǎn)生錯(cuò)誤和帶來(lái)高的維護(hù)成本。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85349.html

相關(guān)文章

  • ES6 變量作用域與提升:變量的生命周期詳解

    摘要:不同的是函數(shù)體并不會(huì)再被提升至函數(shù)作用域頭部,而僅會(huì)被提升到塊級(jí)作用域頭部避免全局變量在計(jì)算機(jī)編程中,全局變量指的是在所有作用域中都能訪問(wèn)的變量。 ES6 變量作用域與提升:變量的生命周期詳解從屬于筆者的現(xiàn)代 JavaScript 開(kāi)發(fā):語(yǔ)法基礎(chǔ)與實(shí)踐技巧系列文章。本文詳細(xì)討論了 JavaScript 中作用域、執(zhí)行上下文、不同作用域下變量提升與函數(shù)提升的表現(xiàn)、頂層對(duì)象以及如何避免創(chuàng)建...

    lmxdawn 評(píng)論0 收藏0
  • 細(xì)說(shuō) Javascript 函數(shù)篇(六) : ?作用域與命名空間

    在之前的介紹中,我們已經(jīng)知道 Javascript 沒(méi)有塊級(jí)作用,只有函數(shù)級(jí)作用域。 function test() { // a scope for(var i = 0; i < 10; i++) { // not a scope // count } console.log(i); // 10 } Javascript 中也沒(méi)有顯示的命名空間,這就...

    VishKozus 評(píng)論0 收藏0
  • 作用域與閉包

    摘要:依然持有對(duì)該作用域的引用,而這個(gè)引用就叫作閉包。無(wú)論通過(guò)何種手段將內(nèi)部函數(shù)傳遞到所在的詞法作用域以外,它都會(huì)持有對(duì)原始定義作用域的引用,無(wú)論在何處執(zhí)行這個(gè)函數(shù)都會(huì)使用閉包。 因?yàn)樽罱?xiàng)目比較少,閑來(lái)覺(jué)得需要學(xué)習(xí)《你不知道的JavaScript》;跟大家分享一下; 什么是作用域 需要一套設(shè)計(jì)良好的規(guī)則來(lái)存儲(chǔ)變量,并且之后可以方便地找到這些變量。這套規(guī)則被稱為作用域 執(zhí)行 var a = ...

    shery 評(píng)論0 收藏0
  • 作用域與作用域鏈

    摘要:作用域首先分為兩個(gè)部分全局作用域和局部作用域。局部作用域在函數(shù)內(nèi)部聲明的變量和函數(shù)保存在函數(shù)的局部作用域中。作用域鏈作用域鏈?zhǔn)且驗(yàn)楹瘮?shù)發(fā)生了嵌套,當(dāng)一個(gè)函數(shù)嵌套在另一個(gè)函數(shù)內(nèi)就發(fā)生了作用域的嵌套。 1.作用域比較復(fù)雜的說(shuō)法是根據(jù)名稱來(lái)查找變量的一套規(guī)則,還有的說(shuō)法是變量數(shù)據(jù)的集合。作用域其實(shí)是指一個(gè)包含了所有在同一個(gè)區(qū)域聲明的變量和函數(shù)的集合,那么如何決定這些變量數(shù)據(jù)和函數(shù)是屬于同一區(qū)...

    Invoker 評(píng)論0 收藏0
  • Js基礎(chǔ)知識(shí)(三) - 作用域與閉包

    摘要:是詞法作用域工作模式。使用可以將變量綁定在所在的任意作用域中通常是內(nèi)部,也就是說(shuō)為其聲明的變量隱式的劫持了所在的塊級(jí)作用域。 作用域與閉包 如何用js創(chuàng)建10個(gè)button標(biāo)簽,點(diǎn)擊每個(gè)按鈕時(shí)打印按鈕對(duì)應(yīng)的序號(hào)? 看到上述問(wèn)題,如果你能看出來(lái)這個(gè)問(wèn)題實(shí)質(zhì)上是考對(duì)作用域的理解,那么恭喜你,這篇文章你可以不用看了,說(shuō)明你對(duì)作用域已經(jīng)理解的很透徹了,但是如果你看不出來(lái)這是一道考作用域的題目,...

    lemanli 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

antyiwei

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<