1. 程式人生 > 其它 >JS this指向問題

JS this指向問題

首先, 明確一點, 沒有巢狀時, 函式中的this指向它的呼叫者.
巢狀函式, 內部的函式的this指向它的呼叫者=>window(不是外層函式)

var a = {
  f: function (params) {
	console.log(this);
	function fn() {
	  console.log(this);
	}
	fn();
  }
};

a.f();

{f: ƒ}
Window {window: Window, self: Window, document: document, name: '', location: Location, …}

其次, 函式既可以在當前執行環境中( this指向物件 ), 又可以在全域性環境中( this指向window )

var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};
var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

或者

var foo = function () { console.log(this.bar) };
var bar = 2;
var obj = {
  foo: function () { console.log(this.bar) },
  bar: 1
};

obj.foo() // 1
foo() // 2

原因: JavaScript 語言之所以有this的設計,跟記憶體裡面的資料結構有關係。

var obj = { foo: 5 };
JavaScript 引擎會先在記憶體裡面,生成一個物件{ foo: 5 },然後把這個物件的記憶體地址賦值給變數obj。
也就是說,變數obj是一個地址(reference)。後面如果要讀取obj.foo,引擎先從obj拿到記憶體地址,然後再從該地址讀出原始的物件,返回它的foo屬性。
原始的物件以字典結構儲存,每一個屬性名都對應一個屬性描述物件。舉例來說,上面例子的foo屬性,實際上是以下面的形式儲存的。

{
  foo: {
    [[value]]: 5
    [[writable]]: true
    [[enumerable]]: true
    [[configurable]]: true
  }
}

當屬性的值是一個函式。
var obj = { foo: function () {} };
這時,引擎會將函式單獨儲存在記憶體中,然後再將函式的地址賦值給foo屬性的value屬性。

{
  foo: {
    [[value]]: 函式的地址
    ...
  }
}

由於函式是一個單獨的值,所以它可以在不同的環境(上下文)執行。???

var f = function () {};
var obj = { f: f };

// 單獨執行
f()

// obj 環境執行
obj.f()

1 函式形參及內部的this指向: 呼叫函式者

function a(){
    var user = "追夢子";
    console.log(this.user); //undefined
    console.log(this);  //Window
}
window.a();或a();//this指向window

var o = {
    user:"追夢子",
    fn:function(){
        console.log(this.user);  //追夢子
    }
}
o.fn();//this指向o

var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //12
        }
    }
}
o.b.fn();////this指向b

2 箭頭函式的this=定義時外層物件的this,因為它根本沒有自己的this,導致內部的this就是外層程式碼塊的this

var obj = {
  foo() {
    console.log(this);
  },
  bar: () => {
    console.log(this);
  }
}

obj.foo() // {foo: ƒ, bar: ƒ}
obj.bar() // window

注意: 因為是箭頭函式,所以他的this是obj的this,即呼叫obj的=>window

3 建構函式this指向物件

function Fn(){
    this.user = "追夢子";
}
var a = new Fn();  //this指向a
console.log(a.user); //追夢子

定時器中的this,指向的是window. =>巢狀函式

setTimeout(function() {
 alert(this); // this -> window 
},500)

元素繫結事件,執行函式中的this,指向的是當前元素

  let $btn = document.getElementById('btn');
  $btn.onclick = function(){
    alert(this); // this -> $btn
  }

物件(全域性)中的this

var age=18
var obj={
	age1:this.age
}
console.log(obj.age1)  //17

只有函式才形成區域性作用域,上面的obj的this實際上是全域性作用域window