一、this–>undefined
ES6的嚴格模式中,如果調用函數中的this或者頂層this将會指向undefined。
<script type="module">
function fn(){
console.log(this);
}
fn(); //undefined
</script>
<script type="module">
console.log(this); //undefined
</script>
二、this–>window
- 非嚴格模式中函數或者頂層中調用this,會被指向window
- 回調函數中預設this的指向是window
- 當使用call、apply、bind時,如果帶入的第一個參數是null或者undefined,this預設會被指向window
三、this–>上下文環境中的this
- 箭頭函數
var obj={
a:function(){
setTimeout(()=>{
this.b();//this就是目前箭頭函數外的上下文環境中this的指向
// setTimeout外面的this是什麼這個箭頭函數中的this就是什麼
},500)
document.addEventListener("click",e=>{
this.clickhandler(e)
// 這裡的this指向addEventListener函數外上下文環境中this的指向
});
},
b:function(){
console.log("aaa");
},
clickhandler:function(e){
}
}
- 對象的屬性中this也是上下環境中this的指向
var c = 20;
var obj = {
c: 10,
a: this.c,
b: function () {
console.log(this.a);
},
};
obj.b(); //20
var a = 100;
var obj = {
a: 10,
c: 50,
b: {
a: 0,
c: this.a,
run: function () {
console.log(this.c);
},
},
};
obj.b.run(); //100
var a = 100;
document.a = -100;
document.addEventListener("click", clickHandler);
function clickHandler(e) {
// this ---> document
var obj = {
a: 10,
c: 50,
b: {
a: 0,
c: this.a,
run: function () {
console.log(this.c);
},
},
};
obj.b.run(); //-100
}
四、this—>函數中的arguments
在函數中使用回調函數時,利用arguments的參數來執行回調函數,被執行的回調函數中this指向的是目前函數arguments.callee.caller函數的arguments。
// fn中的this是fn1中的arguments
var a;
function fn() {
console.log(this);
console.log(this === a);
}
function fn1(f) {
a = arguments;
arguments[0]();
}
fn1(fn);
上面代碼的列印結果如下圖:
var o={
a:function(){
console.log(this); //Arguments [ƒ, callee: ƒ, Symbol(Symbol.iterator): ƒ]
},
b:function(f){
arguments[0]();
},
c:function(){
this.b(this.a)
}
}
o.c();
上面代碼的列印結果如下圖:
五、事件中的this—>事件偵聽的對象 e.currentTarget
document.addEventListener("click", clickHandler);
function clickHandler(e) {
console.log(this); //document
}
六、this被call、apply和bind重新指定為對應的對象
function fn() {
console.log(this);
}
fn.call({ a: 1 }); //{a: 1}
fn.apply({ a: 1 }); //{a: 1}
fn.bind({ a: 1 })(); //{a: 1}
七、對象函數中的this–>目前對象
var obj={
a:1,
b:function(){
console.log(this); //目前對象
}
}
obj.b(); //{a: 1, b: ƒ}
八、ES6類中的this–>目前類的執行個體化對象
- 在執行個體化方法中或者構造函數中調用的this都是目前類的執行個體化的對象
- 在靜态方法中,this就是目前類名或者目前類的構造函數
class Box {
constructor() {
console.log("aaa");
}
// 執行個體化方法
play() {
console.log(this); //this是目前類執行個體化的對象
}
// 靜态方法
static run() {
console.log(this); //this是目前類也是構造函數
console.log("aaaa");
}
}
// 當直接調用Box時Box指的是類,當使用new Box()時Box指的是類裡面的構造函數constructor
var b=new Box();
b.constructor.run();
Box.run();
console.log(b.constructor);
console.log(b.constructor===Box);
注意:隻有執行個體化對象才有屬性constructor。
九、ES5類中的this
function Box() {
console.log("aaa");
if (!(this instanceof Box)) {
return new Box();
}
}
// 相當于ES6類中的執行個體化方法
Box.prototype.play = function () {
console.log(this); //執行個體化的對象
};
// 相當于ES6中的靜态方法
Box.run = function () {
console.log(this); //就是目前類
};
// Box是類也是構造函數
var b = new Box(); //aaa
//當執行執行個體Box時會執行Box函數,并且自動傳回Box的一個執行個體化元素
var c = Box(); //列印兩次aaa
//在ES5中如果不使用new來執行構造函數,構造函數自身也是可以獨自執行的,但是不能傳回執行個體化對象
console.log(b, c); //列印兩個 Box {}
- 通過new執行個體目前Box時,this就是目前執行個體化的對象。
- 如果直接調用函數Box,this就是window或者undefined(嚴格模式下)。
關于ES5和ES6中類的拓展知識:
- 在ES5或者ES6中,類僅允許有且僅有一個構造函數,并且該函數的名稱和類名相同。
- 在ES6中會将構造函數描述成constructor;在ES5中會将構造函數寫成類名。但是不管是ES5還是ES6,執行個體化對象的constructor都是構造函數。
- 構造函數中不允許使用return傳回資料。
小練習:
var obj = {
a: 10,
abc: function () {
setTimeout(() => {
this.a++;
console.log(this.a, "_______"); //11
(function () {
this.a++;
console.log(this.a); //21
}.call(this.c));
}, 1000);
},
c: {
a: 20,
},
};
obj.abc();