this指向詳解及改變它的指向的方法


一、this指向詳解

this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,實際上this的最終指向的是那個調用它的對象(這句話不那么嚴謹,作為一般情況下是可以的)

再加下面的補充,就完美啦:

情況1:如果一個函數中有this,但是它沒有被上一級的對象所調用,那么this指向的就是window,這里需要說明的是在js的嚴格版中this指向的不是window,但是我們這里不探討嚴格版的問題(在嚴格版中的默認的this不再是window,而是undefined。

function a(){ var user = "追夢子"; console.log(this.user); //undefined console.log(this); //Window } a(); //相當於window.a(); //this最終指向的是調用它的對象,這里的函數a實際是被Window對象所點出來的

情況2:如果一個函數中有this,這個函數有被上一級的對象所調用,那么this指向的就是上一級的對象。

var o = {

    user:"追夢子",

    fn:function(){

        console.log(this.user); //追夢子

        console.log(this); //{user: "追夢子", fn: ƒ}

    }

}

 

o.fn(); //this執行時被它的上一級對象o{user: "追夢子", fn: ƒ}調用

情況3:如果一個函數中有this,這個函數中包含多個對象,盡管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象

var o = {

    a:10,

    b:{

        //a:12,

        fn:function(){

            console.log(this.a); //undefind  有兩個對象b和o,所以此this.a指向它的上一級

        }

    },

    fn1:function(){

        console.log(this.a);  //10 

    }

}

o.fn1();

 

o.b.fn();

另外還有兩種種特殊情況:

第一種:當this遇到return

function fn()  

{  

    this.user = '追夢子';  

    return {};  

}

var a = new fn;  

 

console.log(a.user); //undefined

function fn()  

{  

    this.user = '追夢子';  

    return function(){};

}

var a = new fn;  

 

console.log(a.user); //undefined

function fn()  

{  

    this.user = '追夢子';  

    return 1;

}

var a = new fn;  

 

console.log(a.user); //追夢子

function fn()  

{  

    this.user = '追夢子';  

    return undefined;

}

var a = new fn;  

 

console.log(a.user); //追夢子

function fn()  

{  

    this.user = '追夢子';  

    return null;

}

var a = new fn;  

 

console.log(a.user); //追夢子

總結:如果返回值是一個對象,那么this指向的就是那個返回的對象,如果返回值不是一個對象那么this還是指向函數的實例。 
還有一點就是雖然null也是對象,但是在這里this還是指向那個函數的實例,因為null比較特殊。 
第二種:

var o = {

    a:10,

    b:{

        a:12,

        fn:function(){

            console.log(this.a); //undefined

            console.log(this); //window

        }

    }

}

var j = o.b.fn;

 

j();

這里this指向的是window,是不是有些蒙了?其實是因為你沒有理解一句話,這句話同樣至關重要。

  this永遠指向的是最后調用它的對象,也就是看它執行的時候是誰調用的,例子4中雖然函數fn是被對象b所引用,但是在將fn賦值給變量j的時候並沒有執行所以最終指向的是window 
  

二、改變this指向的方法

第一種: new關鍵字改變this指向

//構造函數版this

function Fn(){

    this.user = "追夢子";

}

var a = new Fn();

 

console.log(a.user); //追夢子

用變量a創建了一個Fn的實例(相當於復制了一份Fn到對象a里面),此時僅僅只是創建,並沒有執行,而調用這個函數Fn的是對象a,那么this指向的自然是對象a,那么為什么對象a中會有user,因為你已經復制了一份Fn函數到對象a中,用了new關鍵字就等同於復制了一份

第二種: call()

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this.user); //追夢子

    }

}

var b = a.fn;

 

b.call(a);  //若不用call,則b()執行后this指的是Window對象

把b添加到第一個參數的環境中,簡單來說,this就會指向那個對象。

call方法除了第一個參數以外還可以添加多個參數,如下:

var a = {

    user:"追夢子",

    fn:function(e,ee){

        console.log(this.user); //追夢子

        console.log(e+ee); //3

    }

}

var b = a.fn;

b.call(a,1,2);

第三種:apply()

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this.user); //追夢子

    }

}

var b = a.fn;

 

b.apply(a);

apply方法和call方法有些相似,它也可以改變this的指向,也可以有多個參數,但是不同的是,第二個參數必須是一個數組,如下:

var a = {

    user:"追夢子",

    fn:function(e,ee){

        console.log(this.user); //追夢子

        console.log(e+ee); //11

    }

}

var b = a.fn;

 

b.apply(a,[10,1]);

//注意如果call和apply的第一個參數寫的是null,那么this指向的是window對象

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}

    }

}

var b = a.fn;

 

b.apply(null);

第四種:bind() 
bind方法和call、apply方法有些不同,如下:

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this.user);

    }

}

var b = a.fn;

 

b.bind(a);  //代碼沒有被打印

我們發現代碼沒有被打印,對,這就是bind和call、apply方法的不同,實際上bind方法返回的是一個修改過后的函數。

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this.user);

    }

}

var b = a.fn;

var c = b.bind(a);

 

console.log(c); //function() { [native code] }

函數c看看,能不能打印出對象a里面的user

var a = {

    user:"追夢子",

    fn:function(){

        console.log(this.user); //追夢子

    }

}

var b = a.fn;

var c = b.bind(a);

 

c();

同樣bind也可以有多個參數,並且參數可以執行的時候再次添加,但是要注意的是,參數是按照形參的順序進行的。

var a = {

    user:"追夢子",

    fn:function(e,d,f){

        console.log(this.user); //追夢子

        console.log(e,d,f); //10 1 2

    }

}

var b = a.fn;

var c = b.bind(a,10);

 

c(1,2);

總結: call和apply都是改變上下文中的this並立即執行這個函數,bind方法可以讓對應的函數想什么時候調就什么時候調用,並且可以將參數在執行的時候添加,這是它們的區別

一、this指向詳解

this的指向在函數定義的時候是確定不了的,只有函數執行的時候才能確定this到底指向誰,實際上this的最終指向的是那個調用它的對象(這句話不那么嚴謹,作為一般情況下是可以的)

再加下面的補充,就完美啦:

情況1:如果一個函數中有this,但是它沒有被上一級的對象所調用,那么this指向的就是window,這里需要說明的是在js的嚴格版中this指向的不是window,但是我們這里不探討嚴格版的問題(在嚴格版中的默認的this不再是window,而是undefined。)

function a(){
    var user = "追夢子";
    console.log(this.user); //undefined
    console.log(this); //Window
}
a(); //相當於window.a();
//this最終指向的是調用它的對象,這里的函數a實際是被Window對象所點出來的
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

情況2:如果一個函數中有this,這個函數有被上一級的對象所調用,那么this指向的就是上一級的對象。

var o = {
    user:"追夢子",
    fn:function(){
        console.log(this.user); //追夢子
        console.log(this); //{user: "追夢子", fn: ƒ}
    }
}
o.fn(); //this執行時被它的上一級對象o{user: "追夢子", fn: ƒ}調用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

情況3:如果一個函數中有this,這個函數中包含多個對象,盡管這個函數是被最外層的對象所調用,this指向的也只是它上一級的對象

var o = {
    a:10,
    b:{
        //a:12,
        fn:function(){
            console.log(this.a); //undefind 有兩個對象b和o,所以此this.a指向它的上一級
        }
    },
    fn1:function(){
        console.log(this.a);  //10 
    }
}
o.fn1();
o.b.fn();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

另外還有兩種種特殊情況:

第一種:當this遇到return

function fn() {  
    this.user = '追夢子';  
    return {};  
}
var a = new fn;  
console.log(a.user); //undefined
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
function fn() {  
    this.user = '追夢子';  
    return function(){};
}
var a = new fn;  
console.log(a.user); //undefined
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
function fn() {  
    this.user = '追夢子';  
    return 1;
}
var a = new fn;  
console.log(a.user); //追夢子
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
function fn() {  
    this.user = '追夢子';  
    return undefined;
}
var a = new fn;  
console.log(a.user); //追夢子
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
function fn() {  
    this.user = '追夢子';  
    return null;
}
var a = new fn;  
console.log(a.user); //追夢子
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

總結:如果返回值是一個對象,那么this指向的就是那個返回的對象,如果返回值不是一個對象那么this還是指向函數的實例。 
還有一點就是雖然null也是對象,但是在這里this還是指向那個函數的實例,因為null比較特殊。 
第二種:

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

這里this指向的是window,是不是有些蒙了?其實是因為你沒有理解一句話,這句話同樣至關重要。

  this永遠指向的是最后調用它的對象,也就是看它執行的時候是誰調用的,例子4中雖然函數fn是被對象b所引用,但是在將fn賦值給變量j的時候並沒有執行所以最終指向的是window 
  

二、改變this指向的方法

第一種: new關鍵字改變this指向

//構造函數版this
function Fn(){
    this.user = "追夢子";
}
var a = new Fn();
console.log(a.user); //追夢子
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

用變量a創建了一個Fn的實例(相當於復制了一份Fn到對象a里面),此時僅僅只是創建,並沒有執行,而調用這個函數Fn的是對象a,那么this指向的自然是對象a,那么為什么對象a中會有user,因為你已經復制了一份Fn函數到對象a中,用了new關鍵字就等同於復制了一份

第二種: call()

var a = {
    user:"追夢子",
    fn:function(){
        console.log(this.user); //追夢子
    }
}
var b = a.fn;
b.call(a);  //若不用call,則b()執行后this指的是Window對象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

把b添加到第一個參數的環境中,簡單來說,this就會指向那個對象。

call方法除了第一個參數以外還可以添加多個參數,如下:

var a = {
    user:"追夢子",
    fn:function(e,ee){
        console.log(this.user); //追夢子
        console.log(e+ee); //3
    }
}
var b = a.fn;
b.call(a,1,2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

第三種:apply()

var a = {
    user:"追夢子",
    fn:function(){
        console.log(this.user); //追夢子
    }
}
var b = a.fn;
b.apply(a);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

apply方法和call方法有些相似,它也可以改變this的指向,也可以有多個參數,但是不同的是,第二個參數必須是一個數組,如下:

var a = {
    user:"追夢子",
    fn:function(e,ee){
        console.log(this.user); //追夢子
        console.log(e+ee); //11
    }
}
var b = a.fn;
b.apply(a,[10,1]);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
//注意如果call和apply的第一個參數寫的是null,那么this指向的是window對象
var a = {
    user:"追夢子",
    fn:function(){
        console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}
    }
}
var b = a.fn;
b.apply(null);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

第四種:bind() 
bind方法和call、apply方法有些不同,如下:

var a = {
    user:"追夢子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
b.bind(a);  //代碼沒有被打印
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我們發現代碼沒有被打印,對,這就是bind和call、apply方法的不同,實際上bind方法返回的是一個修改過后的函數。

var a = {
    user:"追夢子",
    fn:function(){
        console.log(this.user);
    }
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //function() { [native code] }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

函數c看看,能不能打印出對象a里面的user

var a = {
    user:"追夢子",
    fn:function(){
        console.log(this.user); //追夢子
    }
}
var b = a.fn;
var c = b.bind(a);
c();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

同樣bind也可以有多個參數,並且參數可以執行的時候再次添加,但是要注意的是,參數是按照形參的順序進行的。

var a = {
    user:"追夢子",
    fn:function(e,d,f){
        console.log(this.user); //追夢子
        console.log(e,d,f); //10 1 2
    }
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

總結: call和apply都是改變上下文中的this並立即執行這個函數,bind方法可以讓對應的函數想什么時候調就什么時候調用,並且可以將參數在執行的時候添加,這是它們的區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM