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