1. 程式人生 > >穩紮穩打JS——this

穩紮穩打JS——this

這裡寫圖片描述

this的值是在執行時確定的

JS中的this究竟代表什麼,這是在程式執行時根據上下文環境確定,可以分為以下幾種情況。

1. 全域性作用域中的this

在全域性作用域中,this指向window物件。

console.log(this);//指向window物件

this.x = 5//在全域性作用域內建立一個x
//與this.x = 5的等價情況:
//var x = 5;
//x = 5;
  • 在全域性作用域中執行var x=5,其實是為window物件建立一個屬性x,並令其等於5。

  • 若定義變數時不加var,JS會認為該變數為全域性變數,會將其當作window物件的屬性。

2. 函式中的this

JS中函式有兩種,直接呼叫的函式稱為普通函式,通過new建立物件的函式稱為建構函式。

2.1 建構函式中的this

建構函式的this指向它所建立的物件,如:

function Person(name){
    this.name = name;//this指向該函式建立的物件person
}
var person = new Person("chaimm");

2.2 普通函式中的this

普通函式的this指向window物件。
若上述例子,直接執行Perosn函式,則其中this代表window物件,因此該函式執行後會建立一個全域性的name。

function
Person(name){
this.name = name;//this指向window } Person("chai");//當作普通函式執行,this指向window物件

3. 物件中的this

物件中的this指向當前物件,如:

var person = {
    name : "chaimm",
    getName : function(){
        return this.name;
    }
}

上述程式碼中this指向函式getName所屬的物件。
但是,如果一個物件的函式中又嵌套了一個函式,這個函式的this指向的卻是window,而並不是其外層的物件。

var person = {
    name : "chaimm",
    setName : function(name){
        (function(name){
            this.name = name; //此時this並不代表person物件,而是代表window物件
        })(name);
    }
}

上述示例中,person物件中有一個getName函式,而getName函式內部又有一個函式,這個函式內部的this指向window物件,而非person物件,這是JS的一個bug!一般作如下處理,規避這個bug:

var person = {
    name : "chaimm",
    setName : function(name){
        var thar = this;//將this賦給that
        (function(name){
            that.name = name;//此時that指向person物件
        })(name);
    }
}

我們在person物件的第一層函式中,將this賦給區域性變數that,然後在第二層函式中使用that,此時that指向person物件,可對person的屬性進行操作。

  • 注意:若將一個物件中的函式賦給一個變數後,再通過該變數呼叫這個函式,此時該函式中的this指向window,而非該物件,如下所示:
var person = {
    name : "chaimm",
    getName : function(){
        return this.name;
    }
}

//將getName函式賦給一個新的變數
var newGetName = person.getName;
//通過新的變數呼叫這個函式,這個函式中的this將指向window
newGetName();//若全域性作用域中沒有name,則將返回undefined

4. 用call和apply函式給this開掛

這兩個函式都能手動指定被呼叫函式內部的this指向哪個物件。

//定義一個建構函式
var Person = function(name){
    this.name = "";
    this.setName = function(name){
        this.name = name;
    }
}

//建立兩個物件
var personA = new Person("A");
var personB = new Person("B");

//使用personA的setName函式去修改personB的name屬性
personA.setName.apply(personB,["C"]);
  • apply用法
    物件A.函式名.apply(物件B, 引數列表);
    當物件B作為apply的第一個引數傳給apply時,物件A的函式中this就指向了物件B,此時物件A的該函式對this的操作將會作用在物件B上,由此實現了用物件A去呼叫物件B的函式。

這裡寫圖片描述