1. 程式人生 > >javascript中this的理解

javascript中this的理解

1、在函式中執行,分嚴格模式和非嚴格模式

非嚴格模式

非嚴格模式                                    嚴格模式
                                             "use strict"
function func(){                             function func(){  
    console.log(this);                            console.log(this);
}                            =====》         }

func()  //this指向window                      func()  //this指向undefined

2、作為物件的方法被呼叫,

作為物件的方法被呼叫時:

var obj = {
    name: '小賀',
    sayName: function(){
        console.log(this.name);
    }    
}
obj.sayName(); //會打印出小賀,this指向obj

將物件的方法,賦值給一個變數被呼叫。

var obj = {
    name: '小賀',
    sayName: function(){
        console.log(this);
    }    
}
var test = obj.sayName; 
test();     //this指向window

3、作為建構函式被呼叫

在呼叫一個建構函式的時候加上 new 這個關鍵字:

function Person (name) {
this.name = name;
    console.log( this );
}
var  p1 = new Person('kk'); //此時,this 指向這個建構函式呼叫的時候例項化出來的物件。

建構函式其實也是一個函式,若將建構函式當做普通函式來呼叫,this 指向 Window

function Person (name) {
    
    this.name = name;
    console.log(this);
}
var  p2 = Person('MM');   //當前的this指向window

4、在定時器中呼叫時,this指向window

setTimeout(function(){
    console.log(this);   //this指向window
},0)

在沒有特殊指向時,setTimeout和setInterval的回撥函式中的this都是指向window。這是因為JS定時器都是定義在window下的。

5、在箭頭函式中的this

1)、箭頭函式實在全域性的作用域下呼叫的。this指向window.

var func = () => {
    console.log(this); 
}
func();   //this指向window

2)、箭頭函式作為物件的一個函式被呼叫時,this指向window。

var obj = {
    name: 'koga',
    func : () => {
        console.log(this);
    }
}
obj.func()      //this 指向 window

3)、結合定時器呼叫時。

var obj = {
    name: 'koga',
    func: function(){
        setTimeout(function(){
            console.log(this); 
        },0)
    }
}
obj.func();  //this指向window 
var obj = {
    name: 'koga',
    func: function(){
        setTimeout(() => {
            console.log(this); 
        },0)
    }
}
obj.func();  //this指向obj

在物件的函式中,普通函式作為定時器的回撥方法執行時,this指向window。箭頭函式作為定時器的回撥方法執行時,this指向定義時所在的物件。

箭頭函式中 this 的值取決於該函式外部非箭頭函式的 this 的值,且不能通過 call() 、 apply() 和 bind() 方法來改變 this 的值。

6、call、apply、bind

func.call(thisArg,arg1,arg2,arg3); 

這樣會立即執行函式func,thisArg是指定執行函式中的this的上下文,後邊的都是執行該函式的引數。

func.apply(thisArg,[array])

會立即執行函式func,thisAgr是指定執行函式中的this的上下文。後邊是執行該函式的引數,它是一個數組。

func.bind(thisArg,arg1,arg2,arg3,arg4)

它不會立即執行,而是返回一個新函式,這個心函式被指定了this的上下文,後邊的是執行該函式時傳入的引數。

function Person (name, age) {
   this.name = name;
   this.age = age;
      console.log(this);
}
var obj = {
      name: 'kk' ,
      age:  6
    };
Person.call(obj, 'mm', 10 );
// obj,{name: "mm", age: 10}
Person .apply(obj, ['mm',10]);
// obj,{name: "mm", age: 10}
var p1 =  Person.bind(obj, 'mm', 10)
var p2 = new p1();
// Person {name: "mm", age: 10}

在這個示例中,call、apply 和 bind 的 this 都指向了 obj,都能正常執行;call、apply 會立即執行函式,call 和 apply 的區別就在於傳遞的引數,call 接收多個引數列表,apply 接收一個包含多個引數的陣列;bind 不是立即執行函式,它返回一個函式,需要執行 p2 才能返回結果,bind 接收多個引數列表。

7、如何修改this的指向。

1)、使用箭頭函式修改this的指向。

var obj = {
    name:'koga',
    func1: function(){
        console.log(this.name);
    },
    func2: function(){
        setTimeout(function(){
            this.func1();
        })
    }
}

這時會報錯,因為這是setTimeout中的this指向的是window,而在window上並未定義func1方法。

var obj = {
    name:'koga',
    func1: function(){
        console.log(this.name);
    },
    func2: function(){
        setTimeout(() => {
            this.func1();
        })
    }
}

這時不會報錯,箭頭函式的this取決於該函式外邊的非箭頭函式的this的指向。也即是func2中的this的指向,即obj。

2)在函式中使用_this = this

var obj = {
    name:'koga',
    func1: function(){
        console.log(this.name);
    },
    func2: function(){
        var _this = this;
        setTimeout(function(){
            _this.func1();
        })
    }
}

此時,func2 也能正常執行。在 func2 中,首先設定 var _this = this,這裡的 this 是指向 func2 的物件 obj,為了防止在 func2 中的 setTimeout 被 window 呼叫而導致的在 setTimeout 中的 this 為 window。我們將 this (指向變數 obj) 賦值給一個變數 _this,這樣,在 func2 中我們使用 _this 就是指向物件 obj 了。

3)、使用call 、apply、bind等方法改變this的指向。