亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript——this、全局變量和局部變量混談

xiaokai / 2630人閱讀

摘要:再來(lái)看書(shū)中的例子變量引用了構(gòu)造函數(shù)新生成的變量,所以相當(dāng)于與。而全局變量是全局對(duì)象的屬性。延伸知識(shí)點(diǎn)最近學(xué),發(fā)現(xiàn)這幾個(gè)知識(shí)點(diǎn)最好形成思維導(dǎo)圖來(lái)理解作用域變量聲明提升全局對(duì)象全局變量引用上下文構(gòu)造函數(shù)原型鏈與原型。

全局變量 可以先看W3C:JavaScript 全局對(duì)象、MDN:this 全局變量,W3C里說(shuō)得很清楚(JavaScript Window - 瀏覽器對(duì)象模型):

        alert(window.eval===eval);                // true
        alert(window.Object===Object);            // true
        alert(window.Math===Math);                // true
        alert(window.document===document);        // true
        // 我們一開(kāi)始就使用那些函數(shù)方法,屬性都是window對(duì)象的屬性嗎?
瀏覽器對(duì)象模型BOM (Browser Object Model) 使 JavaScript 有能力與瀏覽器“對(duì)話(huà)”。

還有一個(gè)DOM(文檔對(duì)象模型,這是對(duì)HTML進(jìn)行操作的根本)這里略過(guò)。

JavaScript就是那么奇葩,我們?cè)诤瘮?shù)外部聲明的所有全局變量,其實(shí)都是全局對(duì)象的屬性!JavaScript除了數(shù)值、布爾、字符串、null、undefined之外,都是對(duì)象(可以添加屬性)!
        // 預(yù)定義的全局變量、函數(shù)(方法)都是window對(duì)象的屬性
        alert(typeof window.Number)            // function
        alert(typeof window.Math)            // object
        alert(typeof window.Math.random)    // function
        // 更改全局變量
        NaN = 11;
        eval = 22;
        Object = 33;
        Math = 44;
        console.log(window.Math);            // 44
        console.log(typeof window.Math)        // number     全局對(duì)象被改寫(xiě)
        
        alert(NaN);     // NaN
        alert(eval);    // 22
        alert(Object);  // 33
        alert(Math);    // 44
        // 這里可能有一個(gè)誤區(qū):全局對(duì)象不是window嗎?
        // 實(shí)際上:window也是另外一個(gè)全局對(duì)象,但是前提是運(yùn)行在瀏覽器端
        // window全局對(duì)象提供了與當(dāng)前窗口、頁(yè)面有關(guān)的諸多屬性與方法。
        // 除了這些與瀏覽器有關(guān)的全局屬性和方法,window對(duì)象還封裝了JS全局對(duì)象,并向外暴露JS全局對(duì)象的屬性與接口
        
看,這些預(yù)定義好的全局對(duì)象、方法我們都可以直接改寫(xiě)(當(dāng)然沒(méi)人去這么干),當(dāng)然有些不能改寫(xiě)(NaN),不同瀏覽器也有不同支持。 具體可以看這兩位大神的總結(jié),相當(dāng)好:JavaScript中的全局對(duì)象介紹 淺析JavaScript中兩種類(lèi)型的全局對(duì)象/函數(shù) 這里開(kāi)始以this的應(yīng)用為主,雜揉了一些知識(shí)。因?yàn)槲业谝淮螌?xiě)這類(lèi)感想文,編排不好后續(xù)會(huì)慢慢更改。 有關(guān)全局變量的測(cè)試:
        var a = 1;
        alert(this.a);    // 1
        alert(this);      // "[object Window]"

這里定義了一個(gè)全局變量a,之后調(diào)用this.athis。結(jié)果大家看到了。全局變量a的作用域是整個(gè)全局對(duì)象內(nèi)可見(jiàn),或者說(shuō)變量a是全局對(duì)象的屬性。不信?看下面:

        var woshiSB = 1;
        console.log(this);
        var write = "";
        for (var i in this) {
            write += i+"
" } document.write(write);

看到了下面那個(gè)了?沒(méi)錯(cuò),還記得for-in語(yǔ)句干啥的嘛?遍歷一個(gè)對(duì)象里的可枚舉屬性(圖中只截取了部分全局對(duì)象(變量)),之后我們發(fā)現(xiàn)了了它woshiSB,這可以說(shuō)在外部環(huán)境、全局上下文環(huán)境中的全局變量是全局對(duì)象的屬性。反過(guò)來(lái),我們也可以通過(guò)在全局對(duì)象里創(chuàng)建一個(gè)全局變量。且,如果能確定上下文(在任何函數(shù)體外部),滿(mǎn)足這個(gè)前提條件,這個(gè)this指的就是全局對(duì)象了。且,我們可以:

        console.log(this.document === document); // true
        console.log(this.Number===Number);       // true
        // 在瀏覽器中,全局對(duì)象為 window 對(duì)象:
        console.log(this === window);     // true
        
        this.a = 37;                      // 此時(shí)this引用指向全局對(duì)象,所以a是全局對(duì)象的屬性
        console.log(window.a);            // 37
        
        window.b = 38;                    // 同樣的,全局對(duì)象window下的屬性是全局變量
        console.log(this.b);              // 38
        
        this.x = 1;
        alert(this.x===window.x)          // true
this引用的幾種情況(依據(jù)上下文) 第一種:

全局上下文(引用自MDN)
在全局運(yùn)行上下文中(在任何函數(shù)體外部),this指代全局對(duì)象,無(wú)論是否在嚴(yán)格模式下。
console.log(this.document === document); // true

// 在瀏覽器中,全局對(duì)象為 window 對(duì)象:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37
關(guān)于嚴(yán)格模式,請(qǐng)看真?究極大神 阮一峰:Javascript 嚴(yán)格模式詳解
        function f1(){
          return this;
        }
        
        f1() === window; // true

不是在嚴(yán)格模式下執(zhí)行,this的值不會(huì)在函數(shù)執(zhí)行時(shí)被設(shè)置,此時(shí)的this的值會(huì)默認(rèn)設(shè)置為全局對(duì)象。
這里提醒一下:嚴(yán)格的說(shuō),this全稱(chēng)叫this引用。注意引用二字。

        function f2(){
          "use strict"; // 這里是嚴(yán)格模式
          return this;
        }
        
        f2() === undefined; // true

在嚴(yán)格模式下,如果this未被執(zhí)行的上下文環(huán)境定義,那么它將會(huì)默認(rèn)為undefined。
所謂上下文,加幾個(gè)字理解,想到語(yǔ)文里的“聯(lián)系上下文”了嗎?對(duì),this引用所處的環(huán)境,或者說(shuō)它位于的作用域。

第二種:
函數(shù)上下文
在函數(shù)內(nèi)部,this的值取決于函數(shù)是如何調(diào)用的。

包括引用的文章也提到:

如果這個(gè)this屬于某個(gè)function,那么this指代的就是調(diào)用該function的對(duì)象。若這種情況下function只是一個(gè)普通的函數(shù),而不是某個(gè)類(lèi)的方法,那么this的指代存在兩種可能:
1.在ECMAScript 3標(biāo)準(zhǔn),以及ECMAScript 5標(biāo)準(zhǔn)的非嚴(yán)格模式下,this指代全局對(duì)象。
2.在ECMAScript 5標(biāo)準(zhǔn)的嚴(yán)格模式下,this指代undefined。

函數(shù)上下文 —— 對(duì)象方法中的this

        var obj = {
            x:"x",
            fn:function () {
                return this.x;
            }
        };
        console.log(obj.fn())

此時(shí),obj.fn()中的this引用將會(huì)指向obj這個(gè)全局對(duì)象,也就是obj.x

        var obj = {x:"x"};
        function test(obj) {
            return this.x;
        };
        obj.fn = test;
        alert(obj.fn());

在何處或者如何定義調(diào)用函數(shù)完全不會(huì)影響到this的行為。我們?cè)诙xobj的時(shí)候定義了一個(gè)obj.fn()方法。但是,我們也可以首先定義函數(shù)然后再將其附屬到o.f。這樣做this的行為也一致。

來(lái)看另一個(gè)例子:

        var f = function (x) {
            this.y = x+1;
        };
        var a = {y:10,op:f};
        var b= {y:20,increment:f};
        
        a.op(100);                 // 通過(guò)a來(lái)調(diào)用f,this引用指向a引用的對(duì)象
        alert(a.y);                // 101
        b.increment(43);           // 通過(guò)b來(lái)調(diào)用,this引用指向b引用的對(duì)象
        alert(b.y);                // 44

f引用的匿名函數(shù)里的this引用指向調(diào)用它的對(duì)象。

函數(shù)上下文 —— 構(gòu)造函數(shù)中的this:

我們來(lái)看CDN的例子(改寫(xiě)過(guò)):

        function c(){
          this.a = 37;
        };
        c.prototype.test = "test";
        
        var o = new c();
        o.sb = "Sb";                                             // o也是對(duì)象
        console.log(o.a);                                        // logs 37
        console.log(o.__proto__===c.prototype);                  // true
        console.log(o.sb);                                       // "Sb"
        Object.prototype.op = "op";
        console.log(c.prototype.__proto__===Object.prototype)    // true
        console.log(Object.prototype.__proto__);                 // null
        console.log(Object.prototype.constructor===Object);      // true

看到這的的默認(rèn)你已經(jīng)懂了構(gòu)造函數(shù)大部分哈。(我們先讀一遍,對(duì),首先要看懂。)

聲明一個(gè)c函數(shù),同時(shí)內(nèi)建一個(gè)this引用,當(dāng)然我們并不知道這個(gè)引用指向誰(shuí)。將c函數(shù)作為構(gòu)造函數(shù)調(diào)用,(此時(shí):構(gòu)造函數(shù)會(huì)隱式生成一個(gè)對(duì)象,對(duì)象內(nèi)建的隱式鏈接指向構(gòu)造函數(shù)的prototype對(duì)象),這個(gè)新對(duì)象的引用賦值給全局變量o,注意是引用賦值,這個(gè)變量同時(shí)也是對(duì)象,Sb那里也看到了?,F(xiàn)在你腦子里是不是生成了一副引用指向圖了呢?把它畫(huà)出來(lái)你就都知道了。

變量o引用了新對(duì)象,則構(gòu)造函數(shù)里的this引用就是指向o,這里展現(xiàn)的是原型鏈,關(guān)于原型鏈我還不夠了解后續(xù)會(huì)繼續(xù)學(xué)習(xí);
再來(lái)看另一個(gè):

        function c2(){
          this.a = 37;
          return {a:38};
        };

        o = new c2();
        console.log(o.a); // logs 38    

在最后的例子中(C2),因?yàn)樵谡{(diào)用構(gòu)造函數(shù)的過(guò)程中,手動(dòng)的設(shè)置了返回對(duì)象,與this綁定的默認(rèn)對(duì)象被取消(本質(zhì)上這使得語(yǔ)句this.a = 37成了“僵尸”代碼,實(shí)際上并不是真正的“僵尸”,這條語(yǔ)句執(zhí)行了但是對(duì)于外部沒(méi)有任何影響,因此完全可以忽略它)?!?引自CDN
其實(shí)我對(duì)CDN的解釋也不太懂,可以認(rèn)為,重新改變o引用的對(duì)象,則也改變了this引用的對(duì)象。則this.a肯定指向新對(duì)象。

再來(lái)看書(shū)中的例子:

        var Point = function (x,y) {
            this.x = x;
            this.y = y;
        };
        var p = new Point(4,-5);
        var q = Point(3,8);
        
        console.log(typeof q);    // "undefined"

p變量引用了構(gòu)造函數(shù)新生成的變量,this.xthis.y所以相當(dāng)于p.xp.y。調(diào)用構(gòu)造函數(shù),傳參后,就賦值等等。
而變量q,注意這里只是將Point當(dāng)做普通函數(shù)調(diào)用而已,執(zhí)行函數(shù)主體后,也沒(méi)有返回值。So,q的值類(lèi)型是undefined。

再來(lái)看另一個(gè)例子:

        var obj = {
            x:3,
            doit:function () {
                console.log("method is called."+this.x);
            }
        };
        // 1
        var fn = obj.doit;            // 將obj.doit引用的Function對(duì)象賦值給全劇變量    
        fn();                         // "method is called.undefined"
        // 2
        var x = 5;
        fn();                         // "method is called.5"
        // 3
        var obj2 = {x:4,doit2:fn};
        obj2.doit2();                 // "method is called.4"  
        

全局變量obj引用對(duì)象,內(nèi)含obj.x和一個(gè)方法,方法內(nèi)存在this引用。

第一次調(diào)用:將對(duì)象內(nèi)部doit方法賦值給全部變量fn,此時(shí)調(diào)用fn。那么我想問(wèn),是誰(shuí)調(diào)用fn呢?是全局對(duì)象。而全局變量是全局對(duì)象的屬性。也就是說(shuō)上下文內(nèi)存在的全局變量都對(duì)全局對(duì)象可見(jiàn),作用域嘛。此時(shí),既然全局對(duì)象調(diào)用函數(shù)方法,則this引用當(dāng)然指向全局對(duì)象??墒牵謱?duì)象并沒(méi)有屬性x(或者說(shuō)沒(méi)有全局變量x)所以是undefined。

第二次調(diào)用//2:就是反證第一次的,說(shuō)明this引用的確引用了全局對(duì)象,或者我們看這個(gè):

        var test = {
            z:"test-z",
            fn:function () {
                console.log(this.z)
            }
        };
        window.fun = test.fn;            // 全局對(duì)象的fun方法
        var z = "var z";                 // 全局變量z
        window.fun();                    // result:"var z"    this引用指向全局對(duì)象
        
        var z1 = "var z1";               // 全局變量z1
        test.z1 = "test.z1";             // 屬性z1
        test.fn2 = function () {console.log(this.z1)}    
        test.fn2();                      // result:"test.z1"        this引用指向test對(duì)象

所以當(dāng)?shù)谌握{(diào)用時(shí),doit2引用的Funcion對(duì)象內(nèi)部的this引用指向的是obj2對(duì)象。相當(dāng)于obj2.x

這里要提一下之后要學(xué)到的applycall方法,它們作用就是顯式的指定this引用要引用的對(duì)象,或者說(shuō)顯式指定接收方對(duì)象。

嵌套一個(gè)來(lái)試試:

        var x = "var x";
        var fn = function () {alert(this.x)};
        var obj = {
            x:"obj.x",
            fn:function () {alert(this.x)},
            obj2:{
                x:"obj2.x",
                fn2:function () {alert(this.x)}
            }
        };
        
        // 直接調(diào)用
        obj.obj2.fn2();        // obj2.x
        obj.fn();              // obj.x
        fn();                  // var z
哪怕跨級(jí)調(diào)用,由于搜索都是按作用域由內(nèi)之外,所以引用的是最近的對(duì)象。所以這應(yīng)該是MDN里那句話(huà)的意思了。
類(lèi)似的,this 的綁定只受最靠近的成員引用的影響

再來(lái)看一個(gè)變形:

        var obj = {
            x:"obj.x",
            doit:function () {
                console.log("doit is called."+this.x);            // 這里的this.x:obj.x
                this.test.doit2();                                
                // 這里的this.x:"test.x"
                //  "true"
            },
            test:{
                x:"test.x",
                doit2:function () {
                    var x = "doit2-x";
                    console.log("doit2 is called."+this.x+" | "+this);
                    // 這里的this.x:"test.x"
                    console.log(this===window.obj.test && this===obj.test);
                    // "true"    this引用指向嵌套對(duì)象:test
                }
            }
        };
        obj.doit();                    // this.x: "obj.x"
        var x = "var z";             
        window.obj.test.doit2();    // this.x:"test.x"
最后提一下原型鏈中的this引用:
        var o = {
          f : function(){ 
            return this.a + this.b; 
          }
        };
        var p = Object.create(o);
        p.a = 1;
        p.b = 4;
        console.log(p.f());             // 5            
        alert(p.__proto__===o);            // true

如果該方法存在于一個(gè)對(duì)象的原型鏈上,那么this指向的是調(diào)用這個(gè)方法的對(duì)象,表現(xiàn)得好像是這個(gè)方法就存在于這個(gè)對(duì)象上一樣。

在這個(gè)例子中,對(duì)象p沒(méi)有屬于它自己的f屬性,它的f屬性繼承自它的原型。但是這對(duì)于最終在o中找到f屬性的查找過(guò)程來(lái)說(shuō)沒(méi)有關(guān)系;查找過(guò)程首先從p.f的引用開(kāi)始,所以函數(shù)中的this指向p。也就是說(shuō),因?yàn)?b>f是作為p的方法調(diào)用的,所以它的this指向了p。這是JavaScript的原型繼承中的一個(gè)有趣的特性。
延伸知識(shí)點(diǎn): 最近學(xué)JS,發(fā)現(xiàn)這幾個(gè)知識(shí)點(diǎn)最好形成思維導(dǎo)圖來(lái)理解:作用域、變量聲明提升、全局對(duì)象全局變量、this引用(上下文)、new構(gòu)造函數(shù)、原型鏈與原型......,continue learning。

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

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

相關(guān)文章

  • JavaScript——作用域、變量聲明提升、局部變量混談

    摘要:主要聊聊局部變量作用域變量聲明提升作用域中有以下兩種作用域全局作用域函數(shù)作用域全局作用域是函數(shù)之外最外層代碼的作用域。相對(duì)于全局作用域,可以稱(chēng)之為局部作用域相對(duì)于全局變量可以將其成為局部變量。然而,這里的是在下一行進(jìn)行聲明的局部變量。 主要聊聊局部變量、作用域、變量聲明提升 作用域 JavaScript中有以下兩種作用域 全局作用域 函數(shù)作用域 全局作用域是函數(shù)之外(最外層代碼)的...

    luffyZh 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記](méi) JavaScript 作用域鏈

    摘要:全局執(zhí)行環(huán)境的變量對(duì)象始終是作用域鏈中的最后一個(gè)變量對(duì)象。綜上,每個(gè)函數(shù)對(duì)應(yīng)一個(gè)執(zhí)行環(huán)境,每個(gè)執(zhí)行環(huán)境對(duì)應(yīng)一個(gè)變量對(duì)象,而多個(gè)變量對(duì)象構(gòu)成了作用域鏈,如果當(dāng)前執(zhí)行環(huán)境是函數(shù),那么其活動(dòng)對(duì)象在作用域鏈的前端。 1.幾個(gè)概念 先說(shuō)幾個(gè)概念:函數(shù)、執(zhí)行環(huán)境、變量對(duì)象、作用域鏈、活動(dòng)對(duì)象。這幾個(gè)東東之間有什么關(guān)系呢,往下看~ 函數(shù) 函數(shù)大家都知道,我想說(shuō)的是,js中,在函數(shù)內(nèi)部有兩個(gè)特殊...

    ?xiaoxiao, 評(píng)論0 收藏0
  • JavaScript 闖關(guān)記》之作用域閉包

    摘要:作用域和閉包是最重要的概念之一,想要進(jìn)一步學(xué)習(xí),就必須理解作用域和閉包的工作原理。全局和局部作用域的關(guān)系在函數(shù)體內(nèi),局部變量的優(yōu)先級(jí)高于同名的全局變量。作用域鏈的用途,是保證對(duì)執(zhí)行環(huán)境有權(quán)訪(fǎng)問(wèn)的所有變量和函數(shù)的有序訪(fǎng)問(wèn)。 作用域和閉包是 JavaScript 最重要的概念之一,想要進(jìn)一步學(xué)習(xí) JavaScript,就必須理解 JavaScript 作用域和閉包的工作原理。 作用域 任何...

    Jacendfeng 評(píng)論0 收藏0
  • JavaScript的作用域

    摘要:函數(shù)的作用域也可被分為全局作用域和局部作用域函數(shù)作用域,被定義在指定函數(shù)內(nèi)部的函數(shù)被稱(chēng)為局部函數(shù)或內(nèi)部函數(shù)。 作用域 變量和函數(shù)都有作用域,作用域就是變量和函數(shù)可被訪(fǎng)問(wèn)的范圍,控制著變量和函數(shù)的可見(jiàn)性和生命周期(生命周期指一個(gè)事物開(kāi)始到結(jié)束中間那一段時(shí)間)變量的作用域可被分為全局作用域和局部作用域(函數(shù)作用域),如果變量是被定義在全局作用域的話(huà),在JavaScript代碼中的任何位置都...

    aikin 評(píng)論0 收藏0
  • JavaScript-作用域、塊級(jí)作用域、上下文、執(zhí)行上下文、作用域鏈

    摘要:一旦函數(shù)執(zhí)行完成,其就會(huì)從作用域鏈頂部移除,并且執(zhí)行權(quán)會(huì)返回到函數(shù)。攀爬作用域鏈當(dāng)不同執(zhí)行上下文之間存在變量命名沖突,可以通過(guò)攀爬作用域鏈解決從頂部到底部。 一、作用域 在 JavaScript 中, 作用域(scope,或譯有效范圍)就是變量和函數(shù)的可訪(fǎng)問(wèn)范圍,即作用域控制著變量和函數(shù)的可見(jiàn)性和生命周期 二、全局/局部作用域 2.1 全局作用域(Global Scope) (1)不...

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

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

0條評(píng)論

閱讀需要支付1元查看
<