javascript中this的問題

  看過很多關於javascript中this指向的問題,現總結如下,如有不正確,歡迎指正。

  javascript中,this的指向並不是在函數定義的時候確定的,而是在其被調用的時候確定的。也就是說,函數的調用方式決定了this指向。記住:this 就是一個指針,指向我們調用函數的對象。

  在此將javascript中this的調用方式分爲以下幾種:

1、直接調用:

  直接調用是指通過 funName(..) 這種方式調用。此時,函數內部的this指向全局變量。

function foo() {
    console.log(this === global);
}
foo(); //true

  注意:直接調用並不是僅僅指在全局作用域下進行調用,而是說在任何作用域下通過funName(..) 這種方式調用。如下兩個例子亦是屬於直接調用方式:

  a、使用bind函數改變外層函數的作用域,然後在內層直接調用,其this指向依然是全局變量:

function foo() {
    console.log(this === global);
}

function foo1() {
    foo();
};
var foo2 = foo1.bind({}); //改變foo1函數的作用域
foo2(); //true 依然指向全局變量

  b、函數表達式,將一個函數賦值給一個變量,然後通過直接調用的調用方式調用此函數,其this指向依然是全局變量:

var obj = {
    foo: function(){
        console.log(this === obj);   //false
        console.log(this === global);//true
    }
}
var f = obj.foo;
f();

2、方法調用:

  方法調用是指通過對象來調用其方法函數,類似於obj.foo(..)的調用方式。此時,this指向調用該方法的對象,注意,是最終調用該方法的對象。

var obj = {
    foo1: function(){
        console.log(this === obj);
    }
}
obj.foo2 = function() {
    console.log(this === obj);
}
function foo3() {
    console.log(this === obj);
}
obj.foo3 = foo3;
obj.foo1(); // true
obj.foo2(); // true
obj.foo3(); // true

3、new 調用:

  在es5中,通過 new Constructor() 的形式調用一個構造函數,會創建這個構造函數實例,而這個實例的this指向創建的這個實例。如下例所示,在構造函數內部使用this.name並沒有改變全局變量name的值。

var name = "全局";
function Person(name){
    this.name = name;
}
var p = new Person("局部");
console.log(p.name);
console.log(name);

上述三種情況是常見的調用方式,以下還有一些特殊的調用方式:如bind、call、apply以及es6中箭頭函數。

4、bind函數對this的影響

  bind函數用於綁定this的指向,並且返回一個綁定函數,此函數綁定了this指向,注意:綁定函數的this指向將不可再次更改。

var obj = {};
function foo1() {
    console.log(this === obj);
}
foo1(); //false  此時屬於上述直接調用的方式,因此其this指向global
var foo2 = foo1.bind(obj);
foo2(); //true 綁定函數的this指向其綁定的對象
/**
 * 注意:綁定函數的this指向不可更改
 */
var foo3 = foo2.bind({'a': 1});
foo3(); //true 
foo2.apply({'a': 1}); //true 
foo2.call({'a': 1});  //true 

5、apply和call對this指向的影響

  apply和call亦可以用於改變this指向,並且返回執行結果。關於bind、apply和call的區別以及實現可以參考我的博客:《bind、call、apply的區別與實現》,在此不做重複說明。需要注意的一點是:apply和call不可以改變綁定函數(使用bind返回的函數)的this指向。

var obj = {};
function foo1() {
    console.log(this === obj);
}
var foo2 = foo1.bind({'a': 1});
/**
 * 注意:此處並不是綁定函數,因此其返回值依然是ture,即apply改變其this指向。
 */
foo1.apply(obj); //true
/**
 * 注意:此處是綁定函數,因此不可再通過apply和call的形式改變其this指向。
 */
foo2.apply(obj); //false

6、es6箭頭函數中的this

  箭頭函數沒有自己的this綁定,其使用的this是其直接父級函數的this。也就是說,箭頭函數內部的this是由其直接外層函數(方法)決定的,而外層函數中的this是由其調用方式決定的。

const obj = {
    foo: function() {
        const inner = () => {
            console.log(this === obj);
        };
        inner();
    },
    far: function() {
        return () => {
            console.log(this === obj);
        }
    }
}
/**
 * inner()內的this是foo的this,其指向取決於foo的調用方式
 */
obj.foo(); //true
var foo1 = obj.foo;
foo1();    //false 此時應該指向global

const far1 = obj.far();
far1();    //true
const far2 = obj.far;
far2()();  //false 此時應該指向global

  以上是個人對JavaScript中this的理解,歡迎您的留言。

轉自:javascript的this問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章