前言
this是JavaScript世界最让人迷惑的关键字之一,如果不明白this的本质,基本上会被一线互联网公司的面试官扣大量的分。上下文问有提到过this是上下文中确定的那么我们来了解下什么是this。
为什么要有this?
function func() {
console.log(aaa);
}
❝如上述代码,函数func打印变量aaa,问题是这个函数func可以在任意其他执行上下文中被调用,因此这个a可能就指向不同了。
❞
「this就是指向当前代码运行时所处的上下文环境」
this的一些理解
「this 既不指向函数自身也不指向函数的作用域」
- this的指向,是在函数被调用的时候确定的,也就是执行上下文被创建时确定的。
- this 的指向和函数声明的位置没有任何关系,只取决于函数的调用位置(也即由谁、在什么地方调用这个函数) 。
- 正因为在执行上下文的创建阶段this的指向就已经被确定了,在执行阶段this指向不可再被更改。
this指向规则
默认指向
「默认this是指向全局对象window的」
function func() {
console.log( this.b ); // this指向全局对象
}
var b = 3;
func(); // 3
- 这是在默认正常执行环境下会执行window
- 如果开启了严格模式,那么func()将会变为undefined,this执行undefiend
function func() {
"use strict";//函数体处于严格模式下,this指向undefined
console.log(this.age);
}
var age = "22";
(function() {
func(); //age of undefined
})();
setTimeout和setInterval指向?
❝可以发现在setInterval和setTimeout中传入函数时,函数中的this会指向window对象
❞
var num = 0;
class Obj {
constructor(num){
this.num = num;
}
func(){
console.log(this.num);
}
func1(){
setTimeout(function () {
console.log("setTimeout:"+this.num);
}, 1000)
}
func2(){
setInterval(function () {
console.log(this.num);
}, 2000)
}
}
var obj = new Obj(1);
obj.func();//>> 1 输出的是obj.num
obj.func1()//>> setTimeout:0 输出的是window.num
obj.func2()//>> 0 0 0 0 …… 输出的是window.num
可能是匿名函数做的鬼>v<,当然可以使用bind进行修正this指向即可解决
隐式this
「通过执行时的上下文来决定,也就是调用的位置。」
function func() {
console.log(this.a);
}
var obj = {
a: 2,
func: func
};
obj.func(); // 2
- 找到调用位置,由 obj 对象来调用函数func,
- 此时可以说函数func被调用时,obj 对象“拥有”或者“包含”func函数,
- 所以此时的 this 指向调用 func 函数的 obj 对象。
隐式丢失?
function func() {
console.log( this.a );
}
var obj = {
a: "coffe1891",
func: func
};
var bar = obj.func; // 间接引用,见本文【壹.2.3.6】。此时bar和obj.func其实
// 都指向内存中的函数func本身。
var a = "oops, global"; // a 是全局对象window的属性,也是全局变量
bar(); //>> oops, global
- 可以理解为 bar 是 obj.func 的一个引用,但是实际上,它引用的是func函数本身
- bar() 其实是一个不带任何定语的独立函数调用,所以就按默认指向,执行window
显式this
❝JavaScript内置对象Function的三个原型方法call()、apply()和bind(),它们的第一个参数是一个对象,它们会把这个对象绑定到this,接着在调用函数时让this指向这个对象。
❞
var a = "makai";
function func() {
console.log( this.a );
}
var obj = {
a:"123123"
};
func.call(obj); // 123123
// 在调用 func 时强制把它的 this 绑定到 obj 上
bind和call就不用我多说了把 bind不会立即执行,而apply会立即执行和call一样,区别在于传参不同
new中的this
「通过 new的方式,this永远指向新创建的对象」
function func(name) {
this.name = name;
this.getName = function() {
return this.name;
};
}
var obj = new func("biubiubiu"); //this会指向obj
obj.getName()//biubiubiu
箭头函数的this
❝箭头函数的自身是没有this的,箭头函数的 this与声明所在的上下文相同, 默认为window,严格模式为undefined
❞
var b = 11
var obj = {
b: 22,
a: () => {
console.log(this.b);
}
}
// 对象调用箭头函数
obj.a(); // 11 thi=>window
over 快乐每一天
本文使用 mdnice 排版