成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JS 中 this 關(guān)鍵字詳解

zoomdong / 2631人閱讀

摘要:首先,必須搞清楚在里面,函數(shù)的幾種調(diào)用方式普通函數(shù)調(diào)用作為方法來調(diào)用作為構(gòu)造函數(shù)來調(diào)用使用方法來調(diào)用方法箭頭函數(shù)但是不管函數(shù)是按哪種方法來調(diào)用的,請記住一點誰調(diào)用這個函數(shù)或方法關(guān)鍵字就指向誰。

本文主要解釋在JS里面this關(guān)鍵字的指向問題(在瀏覽器環(huán)境下)。

首先,必須搞清楚在JS里面,函數(shù)的幾種調(diào)用方式:

普通函數(shù)調(diào)用

作為方法來調(diào)用

作為構(gòu)造函數(shù)來調(diào)用

使用apply/call方法來調(diào)用

Function.prototype.bind方法

es6箭頭函數(shù)

但是不管函數(shù)是按哪種方法來調(diào)用的,請記住一點:誰調(diào)用這個函數(shù)或方法,this關(guān)鍵字就指向誰。

接下來就分情況來討論下這些不同的情況:

普通函數(shù)調(diào)用
    function person(){
        this.name="xl";
        console.log(this);
        console.log(this.name);
    }
    
    person();  //輸出  window  xl   
    

在這段代碼中person函數(shù)作為普通函數(shù)調(diào)用,實際上person是作為全局對象window的一個方法來進(jìn)行調(diào)用的,即window.person();
所以這個地方是window對象調(diào)用了person方法,那么person函數(shù)當(dāng)中的this即指window,同時window還擁有了另外一個屬性name,值為xl.

    var name="xl";
    function person(){
        console.log(this.name);
    }
    person(); //輸出 xl

同樣這個地方person作為window的方法來調(diào)用,在代碼的一開始定義了一個全局變量name,值為xl,它相當(dāng)于window的一個屬性,即window.name="xl",又因為在調(diào)用person的時候this是指向window的,因此這里會輸出xl.

作為方法來調(diào)用

在上面的代碼中,普通函數(shù)的調(diào)用即是作為window對象的方法進(jìn)行調(diào)用。顯然this關(guān)鍵字指向了window對象.

再來看下其他的形式

    var name="XL";
    var person={
        name:"xl",
        showName:function(){
            console.log(this.name);
        }
    }
    person.showName();  //輸出  xl
    //這里是person對象調(diào)用showName方法,很顯然this關(guān)鍵字是指向person對象的,所以會輸出name
    
    var showNameA=person.showName;
    showNameA();    //輸出  XL
    //這里將person.showName方法賦給showNameA變量,此時showNameA變量相當(dāng)于window對象的一個屬性,因此showNameA()執(zhí)行的時候相當(dāng)于window.showNameA(),即window對象調(diào)用showNameA這個方法,所以this關(guān)鍵字指向window

再換種形式:

    var personA={
        name:"xl",
        showName:function(){
            console.log(this.name);
        }
    }
    var personB={
        name:"XL",
        sayName:personA.showName
    }
    
    personB.sayName();  //輸出 XL
    //雖然showName方法是在personA這個對象中定義,但是調(diào)用的時候卻是在personB這個對象中調(diào)用,因此this對象指向
作為構(gòu)造函數(shù)來調(diào)用
    function  Person(name){
        this.name=name;
    }
    var personA=Person("xl");
    console.log(personA.name); // 輸出  undefined
    console.log(window.name);//輸出  xl
    //上面代碼沒有進(jìn)行new操作,相當(dāng)于window對象調(diào)用Person("xl")方法,那么this指向window對象,并進(jìn)行賦值操作window.name="xl".
    
    var personB=new Person("xl");
    console.log(personB.name);// 輸出 xl
    //這部分代碼的解釋見下
    
new操作符
    //下面這段代碼模擬了new操作符(實例化對象)的內(nèi)部過程
    function person(name){
        var o={};
        o.__proto__=Person.prototype;  //原型繼承
        Person.call(o,name);
        return o;
    }
    var personB=person("xl");
    
    console.log(personB.name);  // 輸出  xl
    

person里面首先創(chuàng)建一個空對象o,將o的proto指向Person.prototype完成對原型的屬性和方法的繼承

Person.call(o,name)這里即函數(shù)Person作為apply/call調(diào)用(具體內(nèi)容下方),將Person對象里的this改為o,即完成了o.name=name操作

返回對象o。

因此`person("xl")`返回了一個繼承了`Person.prototype`對象上的屬性和方法,以及擁有`name`屬性為"xl"的對象,并將它賦給變量`personB`.
所以`console.log(personB.name)`會輸出"xl"

call/apply方法的調(diào)用

在JS里函數(shù)也是對象,因此函數(shù)也有方法。從Function.prototype上繼承到Function.prototype.call/Function.prototype.apply方法
call/apply方法最大的作用就是能改變this關(guān)鍵字的指向.

Obj.method.apply(AnotherObj,arguments);

    var name="XL";
    var Person={
        name:"xl",
        showName:function(){
            console.log(this.name);
        }
    }
    Person.showName.call(); //輸出 "XL"
    //這里call方法里面的第一個參數(shù)為空,默認(rèn)指向window。
    //雖然showName方法定義在Person對象里面,但是使用call方法后,將showName方法里面的this指向了window。因此最后會輸出"XL";
    funtion FruitA(n1,n2){
        this.n1=n1;
        this.n2=n2;
        this.change=function(x,y){
            this.n1=x;
            this.n2=y;
        }
    }
    
    var fruitA=new FruitA("cheery","banana");
    var FruitB={
        n1:"apple",
        n2:"orange"
    };
    fruitA.change.call(FruitB,"pear","peach");
    
    console.log(FruitB.n1); //輸出 pear
    console.log(FruitB.n2);// 輸出 peach

FruitB調(diào)用fruitAchange方法,將fruitA中的this綁定到對象FruitB上。

Function.prototype.bind()方法
    var name="XL";
    function Person(name){
        this.name=name;
        this.sayName=function(){
            setTimeout(function(){
                console.log("my name is "+this.name);
            },50)
        }
    }
    var person=new Person("xl");
    person.sayName()  //輸出  “my name is XL”;
                       //這里的setTimeout()定時函數(shù),相當(dāng)于window.setTimeout(),由window這個全局對象對調(diào)用,因此this的指向為window, 則this.name則為XL 

那么如何才能輸出"my name is xl"呢?

    var name="XL";
    function Person(name){
        this.name=name;
        this.sayName=function(){
            setTimeout(function(){
                console.log("my name is "+this.name);
            }.bind(this),50)  //注意這個地方使用的bind()方法,綁定setTimeout里面的匿名函數(shù)的this一直指向Person對象
        }
    }
    var person=new Person("xl");
    person.sayName(); //輸出 “my name is xl”;

這里setTimeout(function(){console.log(this.name)}.bind(this),50);,匿名函數(shù)使用bind(this)方法后創(chuàng)建了新的函數(shù),這個新的函數(shù)不管在什么地方執(zhí)行,this都指向的Person,而非window,因此最后的輸出為"my name is xl"而不是"my name is XL"

另外幾個需要注意的地方:
setTimeout/setInterval/匿名函數(shù)執(zhí)行的時候,this默認(rèn)指向window對象,除非手動改變this的指向。在《javascript高級程序設(shè)計》當(dāng)中,寫到:“超時調(diào)用的代碼(setTimeout)都是在全局作用域中執(zhí)行的,因此函數(shù)中的this的值,在非嚴(yán)格模式下是指向window對象,在嚴(yán)格模式下是指向undefined”。本文都是在非嚴(yán)格模式下的情況。

    var name="XL";
    function Person(){
        this.name="xl";
        this.showName=function(){
            console.log(this.name);
        }
        setTimeout(this.showName,50);
    }
    var person=new Person(); //輸出 "XL"
    
    //在setTimeout(this.showName,50)語句中,會延時執(zhí)行this.showName方法
    //this.showName方法即構(gòu)造函數(shù)Person()里面定義的方法。50ms后,執(zhí)行this.showName方法,this.showName里面的this此時便指向了window對象。則會輸出"XL";

修改上面的代碼:

    var name="XL";
    function Person(){
        this.name="xl";
        var that=this;
        this.showName=function(){
            console.log(that.name);
        }
        setTimeout(this.showName,50)
    }
    var person=new Person(); //輸出 "xl"
    //這里在Person函數(shù)當(dāng)中將this賦值給that,即讓that保存Person對象,因此在setTimeout(this.showName,50)執(zhí)行過程當(dāng)中,console.log(that.name)即會輸出Person對象的屬性"xl"

匿名函數(shù):

    var name="XL";
    var person={
        name:"xl",
        showName:function(){
            console.log(this.name);
        }
        sayName:function(){
            (function(callback){
                callback();
            })(this.showName)
        }
    }
    person.sayName();  //輸出 XL
    var name="XL";
    var person={
        name:"xl",
        showName:function(){
            console.log(this.name);
        }
        sayName:function(){
            var that=this;
            (function(callback){
                callback();
            })(that.showName)
        }
    }
    person.sayName() ;  //輸出  "xl"
    //匿名函數(shù)的執(zhí)行同樣在默認(rèn)情況下this是指向window的,除非手動改變this的綁定對象
Eval函數(shù)

該函數(shù)執(zhí)行的時候,this綁定到當(dāng)前作用域的對象上

    var name="XL";
    var person={
        name:"xl",
        showName:function(){
            eval("console.log(this.name)");
        }
    }
    
    person.showName();  //輸出  "xl"
    
    var a=person.showName;
    a();  //輸出  "XL"
箭頭函數(shù)

es6里面this指向固定化,始終指向外部對象,因為箭頭函數(shù)沒有this,因此它自身不能進(jìn)行new實例化,同時也不能使用call, apply, bind等方法來改變this的指向

   function Timer() {
        this.seconds = 0;
        setInterval( () => this.seconds ++, 1000);
    } 
    
    var timer = new Timer();
    
    setTimeout( () => console.log(timer.seconds), 3100);
    
    // 3
    
    在構(gòu)造函數(shù)內(nèi)部的setInterval()內(nèi)的回調(diào)函數(shù),this始終指向?qū)嵗膶ο?,并獲取實例化對象的seconds的屬性,每1s這個屬性的值都會增加1。否則最后在3s后執(zhí)行setTimeOut()函數(shù)執(zhí)行后輸出的是0
參考資料

javascript中this詳解

深入淺出javascript中的this

setTimeout中this的指向問題

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/85844.html

相關(guān)文章

  • 詳解js和jquery里的this關(guān)鍵字

    摘要:出于這個原因,該函數(shù)返回的,所以在這里指的是,所以返回的是第一個說明關(guān)鍵字通常在對象的構(gòu)造函數(shù)中使用,用來引用對象。重寫無法重寫,因為它是一個關(guān)鍵字。結(jié)論,表示當(dāng)前的上下文對象是一個對象,可以調(diào)用對象所擁有的屬性,方法。 在《javaScript語言精粹》這本書中,把 this 出現(xiàn)的場景分為四類,簡單的說就是: 有對象就指向調(diào)用對象 沒調(diào)用對象就指向全局對象 用new構(gòu)造就指向新對...

    LoftySoul 評論0 收藏0
  • javascriptnew關(guān)鍵字詳解

    摘要:本文給大家詳細(xì)介紹了下中關(guān)鍵字的使用方法,以及使用關(guān)鍵字的區(qū)別,有需要的小伙伴可以參考下。第行通過關(guān)鍵字創(chuàng)建了一個新對象行對象嘗試訪問和屬性,并調(diào)用方法。一般情況下,函數(shù)對象在產(chǎn)生時會內(nèi)置屬性并將函數(shù)名作為賦值僅函數(shù)對象。 本文給大家詳細(xì)介紹了下javascript中new關(guān)鍵字的使用方法,以及javascript 使用new關(guān)鍵字的區(qū)別,有需要的小伙伴可以參考下。 function ...

    alaege 評論0 收藏0
  • JavaScript深入淺出

    摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點提及,但是只要善于運(yùn)用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強(qiáng)大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...

    blair 評論0 收藏0
  • JavaScript this詳解

    摘要:作為構(gòu)造函數(shù)調(diào)用中沒有類,但是可以從構(gòu)造器中創(chuàng)建對象,并提供了運(yùn)算符來進(jìn)行調(diào)用該構(gòu)造器。構(gòu)造器的外表跟普通函數(shù)一樣,大部分的函數(shù)都可以當(dāng)做構(gòu)造器使用。如果構(gòu)造函數(shù)顯式的返回一個對象,那么則會指向該對象。 this 的指向 this 是 js 中定義的關(guān)鍵字,它自動定義于每一個函數(shù)域內(nèi),但是它的指向卻讓人很迷惑。在實際應(yīng)用中,this 的指向大致可以分為以下四種情況。 1.作為普通函數(shù)調(diào)...

    cyrils 評論0 收藏0
  • JS的閉包與this詳解

    摘要:刪除對匿名函數(shù)的引用,以便釋放內(nèi)存在匿名函數(shù)從中被返回后,它的作用域鏈被初始化為包含函數(shù)的活動對象和全局變量對象。閉包與變量我們要注意到,閉包只能取到任意變量的最后值,也就是我們保存的是活動對象,而不是確定值。 工作中會遇到很多 this對象 指向不明的問題,你可能不止一次用過 _self = this 的寫法來傳遞this對象,它每每會讓我們覺得困惑和抓狂,我們很可能會好奇其中到底發(fā)...

    fireflow 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<