小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

javascript 作用域和 this 關(guān)鍵字

 瞻云軒 2016-03-01

在javascript中存在著this和scope兩個(gè)概念,如果不細(xì)心了解,還真搞不清楚這兩個(gè)概念,今天我們就來詳細(xì)了解一下this和scope的區(qū)別以及它們的作用,最后會(huì)附上code以加深理解。

一、作用域(scope)

所謂作用域就是:變量在聲明它們的函數(shù)體以及這個(gè)函數(shù)體嵌套的任意函數(shù)體內(nèi)都是有定義的。

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function scope(){
    var foo = "global";
    if(window.getComputedStyle){
        var a = "I'm if";
        console.log("if:"+foo); //if:global
    }
    while(1){
        var b = "I'm while";
        console.log("while:"+foo);//while:global
        break;
    }
    !function (){
        var c = "I'm function";
        console.log("function:"+foo);//function:global
    }();
    console.log(
         foo,//global
         a, // I'm if
         b, // I'm while
         c  // c is not defined
    );
}
scope();

(1)scope函數(shù)中定義的foo變量,除過自身可以訪問以外,還可以在if語(yǔ)句、while語(yǔ)句和內(nèi)嵌的匿名函數(shù)中訪問。 因此,foo的作用域就是scope函數(shù)體。

(2)在javascript中,if、while、for 等代碼塊不能形成獨(dú)立的作用域。因此,javascript中沒有塊級(jí)作用域,只有函數(shù)作用域。

 但是,在JS中有一種特殊情況:

 如果一個(gè)變量沒有使用var聲明,window便擁有了該屬性,因此這個(gè)變量的作用域不屬于某一個(gè)函數(shù)體,而是window對(duì)象。

JavaScript
1
2
3
4
5
6
function varscope(){
    foo = "I'm in function";
    console.log(foo);//I'm in function
}
varscope();
console.log(window.foo); //I'm in function

二、作用域鏈(scope chain)

     所謂作用域鏈就是:一個(gè)函數(shù)體中嵌套了多層函數(shù)體,并在不同的函數(shù)體中定義了同一變量, 當(dāng)其中一個(gè)函數(shù)訪問這個(gè)變量時(shí),便會(huì)形成一條作用域鏈(scope chain)。

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
foo = "window";
function first(){
    var foo = "first";
    function second(){
       var foo = "second";
       console.log(foo);
    }
    function third(){
       console.log(foo);
    }
    second(); //second
    third();  //first
}
first();

當(dāng)執(zhí)行second時(shí),JS引擎會(huì)將second的作用域放置鏈表的頭部,其次是first的作用域,最后是window對(duì)象,于是會(huì)形成如下作用域鏈:

second->first->window,  此時(shí),JS引擎沿著該作用域鏈查找變量foo, 查到的是”second”

當(dāng)執(zhí)行third時(shí),third形成的作用域鏈:third->first->window, 因此查到的是:”frist”

特殊情況:with語(yǔ)句

JS中的with語(yǔ)句主要用來臨時(shí)擴(kuò)展作用域鏈,將語(yǔ)句中的對(duì)象添加到作用域的頭部。with語(yǔ)句結(jié)束后,作用域鏈恢復(fù)正常。

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
foo = "window";
function first(){
    var foo = "first";
    function second(){
       var foo = "second";
       console.log(foo);
    }
    function third(obj){
       console.log(foo); //first
       with (obj){
           console.log(foo); //obj
       }
       console.log(foo); //first
    }
    var obj = {foo:'obj'};
    third(obj);
}
first();

在執(zhí)行third()時(shí),傳遞了一個(gè)obj對(duì)象,obj中有屬性foo, 在執(zhí)行with語(yǔ)句時(shí),JS引擎將obj放置在了原鏈表的頭部,于是形成的作用域鏈如下:

obj->third->first->window, 此時(shí)查找到的foo就是obj中的foo,因此輸出的是:”obj”, 而在with之前和之后,都是沿著原來的鏈表進(jìn)行查找,從而說明,在with語(yǔ)句結(jié)束后,作用域鏈已恢復(fù)正常。

三、this 關(guān)鍵字

     在一個(gè)函數(shù)中,this總是指向當(dāng)前函數(shù)的所有者對(duì)象,this總是在運(yùn)行時(shí)才能確定其具體的指向, 也才能知道它的調(diào)用對(duì)象。

     這句話總結(jié)了關(guān)于this的一切,切記,切記,切記!(ps:重要的事情說三遍!)

JavaScript
1
2
3
4
5
6
7
8
window.name = "window";
function f(){
    console.log(this.name);
}
f();//window
var obj = {name:'obj'};
f.call(obj); //obj

在執(zhí)行f()時(shí),此時(shí)f()的調(diào)用者是window對(duì)象,因此輸出”window”

f.call(obj) 是把f()放在obj對(duì)象上執(zhí)行,相當(dāng)于obj.f(),此時(shí)f中的this就是obj,所以輸出的是”obj”

四、實(shí)戰(zhàn)應(yīng)用

code1:

JavaScript
1
2
3
4
5
6
7
8
9
10
11
var foo = "window";
var obj = {
    foo : "obj",
    getFoo : function(){
        return function(){
            return this.foo;
        };
    }
};
var f = obj.getFoo();
f(); //window

code2:

1
2
3
4
5
6
7
8
9
10
11
12
var foo = "window";
var obj = {
    foo : "obj",
    getFoo : function(){
        var that = this;
        return function(){
            return that.foo;
        };
    }
};
var f = obj.getFoo();
f(); //obj

code1和code2是對(duì)this和scope最好的總結(jié),如果對(duì)于運(yùn)行結(jié)果有疑惑,歡迎討論!

代碼解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
code1:
執(zhí)行var  f = obj.getFoo()返回的是一個(gè)匿名函數(shù),相當(dāng)于:
var f = function(){
     return this.foo;
}
f() 相當(dāng)于window.f(), 因此f中的this指向的是window對(duì)象,this.foo相當(dāng)于window.foo, 所以f()返回"window"
code2:
執(zhí)行var f = obj.getFoo() 同樣返回匿名函數(shù),即:
var f = function(){
     return that.foo;
}
唯一不同的是f中的this變成了that, 要知道that是哪個(gè)對(duì)象之前,先確定f的作用域鏈:f->getFoo->window 并在該鏈條上查找that,此時(shí)可以發(fā)現(xiàn)that指代的是getFoo中的this, getFoo中的this指向其運(yùn)行時(shí)的調(diào)用者,從var f = obj.getFoo() 可知此時(shí)this指向的是obj對(duì)象,因此that.foo 就相當(dāng)于obj.foo,所以f()返回"obj"

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多