JavaScript中this的指向問題

this是什麼

  • this是JavaScript的一個關鍵字。
  • this是在函數運行時,在函數體內自動生成的一個對象。
  • this只能在函數體內使用。

在JavaScript中,函數的幾種調用方式

  • 普通函數調用
  • 作爲方法調用
  • 構造函數調用
  • call/apply中
  • Function.prototype.bind中
  • 箭頭函數中

this的幾種指向

  • 哪個對象調用這個函數/方法,this就指向誰
  • 箭頭函數的this指向定義的時候離他最近的對象
  • 箭頭函數不綁定this,不會自己創建this,只能從自己的作用域的上一層繼承this
  • 外層普通函數的this,會在函數調用時發生變化,進而影響箭頭函數的this變化

示例一

var x = 111
var test = {
    x : 222
}
var temp = {
    x : 333,
    do : function(){
        alert(this.x)
    }
}
temp.do()   // 333
test.do = temp.do
test.do()   // 222
var foo = test.do
foo()       // 111

示例二

var name = 'window'
var person1 = {
  name: 'person1',
  show1: function(){
    console.log(this.name)
  }
}
var person2 = {
  name: 'person2'
}
person1.show1();              // person,this指向person1對象
person1.show1.call(person2);  // person2,this指向person2對象

示例三

var name = 'window'
var person1 = {
  name: 'person1',
  show2: () => console.log(this.name)
}
var person2 = {
  name: 'person2'
}
person1.show2();            // window,箭頭函數的this和最近的普通function相同,沒有,指向window
person1.show2.call(person2);// window,無法和person2綁定,所以也是window

示例四

var name = 'window'
var person1 = {
  name: 'person1',
  show3: function(){
    return function(){
      console.log(this.name);
    }
  }
}
var person2 = {
  name: 'person2'
}

person1.show3()();              // window
person1.show3().call(person2);  // person2 
person1.show3.call(person2)();  // window


// 此問題牽扯到閉包的問題

/* 
person1.show3()(); // window
等價於:
var fun = person1.show3();
fun();            // window 

裏面的匿名函數被返回到person1外邊,再調用這個函數時,this指向了window
*/

/* 
person1.show3().call(person2); 
等價於:
var fun = person1.show3();
fun.call(person2);      // person2 

將匿名函數的this和person2綁定了
*/

/* 
person1.show3.call(person2)();  // window
等價於
var fun = person2.show3()
fun() 

在第一階段綁定了person2,這時候匿名函數還沒執行,等再執行時,綁定到了window上
*/

示例五

var name = 'window'
var person1 = {
  name: 'person1',
  show4: function(){
    return () => console.log(this.name)
  }
}
var person2 = {
  name: 'person2'
}

person1.show4()();              // person1
person1.show4().call(person2);  // person1
person1.show4.call(person2)();  // person2

// 這裏涉及了箭頭函數this的指向:最近一層的普通函數綁定的this,且定義時this就被定義好了

/* 
person1.show4()(); 
等價於:
var fun = person1.show4(); // 定義時,this指向了person1
fun();           
*/


/* 
person1.show4().call(person2); 
等價於:
var fun = person1.show4();  // 定義時指向person1,而call不起作用
fun.call(person2); 
*/


/* 
person1.show4.call(person2)(); 
等價於
var fun = person2.show4()  // 將箭頭函數最近的一層普通函數的this指向了person2,再執行時,this就指向了person2
fun() 
*/

示例六

var name = 'window'
function Person(name){
  this.name = name
  this.show5 = function(){
    return () => console.log(this.name)
  }
}
var personA = new Person("personA");
var personB = new Person("personB");

personA.show5()();              // personA
personA.show5().call(personB);  // personA
personA.show5.call(personB)();  // personB

示例七

var name = 'window'

function Person(name) {
  this.name = name;
  this.show1 = function () {
    console.log(this.name)
  }
  this.show2 = () => console.log(this.name)
  this.show3 = function () {
    return function () {
      console.log(this.name)
    }
  }
  this.show4 = function () {
    return () => console.log(this.name)
  }
}

var personA = new Person('personA')
var personB = new Person('personB')

personA.show1()               // personA
personA.show1.call(personB)   // personB

personA.show2()               // personA
personA.show2.call(personB)   // personA

personA.show3()()             // window
personA.show3().call(personB) // personB
personA.show3.call(personB)() // window

personA.show4()()             // personA
personA.show4().call(personB) // personA
personA.show4.call(personB)() // personB

示例八

var name = 'window'
function foo(){
  var name = 'inner';
  console.log(this.name)
}
foo();  // window
// foo在全局全局執行,this指向window
_________________________________________

var name = 'window'
function foo(){
  'use strict'
  var name = 'inner';
  console.log(this)
}
foo();  // undefined
// 這裏this.name會報錯,因爲this是undefined
// 在嚴格模式下

示例九

function foo(){
  setTimeout(() => {
    console.log("id:" + this.id)
    setTimeout( () => {
      console.log("id:" + this.id)
    },100)
  },100)
}
foo.call({id:'111'})  // 111 111

function foo(){
  setTimeout(function(){
    console.log(this.id)
    setTimeout(function(){
      console.log(this.id)
    },100)
  },100)
}
foo.call({id:'111'})  //  undefined undefined


function foo1(){
  setTimeout(() =>{
    console.log("id:", this.id)
      setTimeout(function (){
        console.log("id:", this.id)
      }, 100);
  }, 100);
}
foo1.call({ id: 111 });  // 111 undefined

示例十

// 嵌套箭頭函數
function foo(){
  return () => {
    return () => {
      return () => {
        console.log(this.id)
      }
    }
  }
}

var f = foo.call({id: 1});
var t1 = f.call({id: 2})()();  // 1
var t2 = f().call({id: 3})();  // 1
var t3 = f()().call({id: 4});  // 1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章