前端this指向口诀,this的特点
🗣普通函数的this:指向它的调用者,如果没有调用者则默认指向window。需要注意的是:构造函数里的函数的this指向new后的实例,挂载到原型上的普通方法的this指向new后的示例(后面会有例子,第3点和第4点)
🗣箭头函数的this:指向它定义时的上下文作用域,而与调用者无关。需要注意的是:挂载到构造函数的原型上的箭头函数仍然取决于定义时的上下文作用域(后面会有例子,第4点)
1.普通和箭头函数
1)非严格模式—普通函数的this指向windows
var name = "windows";
function fun() {
console.log(this.name);
}
fun(); // 结果:windows
// 按照口诀fun()没有调用者就指向windows。
// 其实这里的fun()等价于window.fun(),可以理解为是window调用了fun(),所以this指向windos
2)严格模式—普通函数的this指向undefined
function fun() {
"use strict"
console.log(this); // 结果:undefined
}
3)箭头函数this指向
var name = "windows";
var arrowFun=()=>{
console.log(this.name);
}
arrowFun(); // 结果:windows
// 原因:箭头函数this指向取决于它定义时的父级作用域
2.对象中的函数
1)示例:一层对象中的普通函数
var name = "windows";
var obj = {
name: "obj",
fun: function () {
console.log(this.name);
}
}
obj.fun(); // 结果:obj。
// 因为是obj调用了fun(),所以this指向obj
2)示例:一层对象中的箭头函数
var name = "windows";
var obj = {
name: "objFun",
arrawFun: () => {
console.log(this.name); // 结果:windows
}
}
obj.arrawFun(); // 结果:windows
// 原因:箭头函数的this取决于父级作用域,父级是对象没有自己独立的作用域而是位于全局,所以向上延申,找到了window
3)示例:两层对象中的普通函数
var name = "windows";
var obj = {
name: "obj",
fun: function () {
console.log(this.name); // 结果:obj
},
obj2: {
name: "obj2",
fun:function () {
console.log(this.name); // 结果:obj2
}
}
}
obj.fun(); // 结果:obj。
obj.obj2.fun(); // 结果:obj2
// 原因还是;普通函数的this谁调用就指向谁
4)示例:两层对象中的箭头函数
var name = "windows";
var obj = {
name: "obj",
obj2: {
name: "obj2",
arrawFun:()=> {
console.log(this.name); // 结果:windows
}
}
}
obj.obj2.arrawFun(); // 结果:windows
// 原因;箭头函数的this取决于父级作用域,父级是对象没有自己独立的作用域
// 所以向上延申一层,但还是对象,所以再向上延申一层,就找到了window
5)示例:对象里的方法返回普通方法
var name = "windows";
var obj = {
name: "obj",
fun: function () {
return function(){
console.log(this.name);
}
}
}
obj.fun(); // 结果:ƒ (){console.log(this.name);}
obj.fun()(); // 结果:windows
// 原因:obj.fun()执行后返回一个方法,所以再加一对“()”会执行
// 执行的时候这个方法相当于被全局调用,所以this指向window。
// 但实质上从对象中返回方法,目的肯定在于使用对象中的属性
// 所就就有了`var that=this;`这样的语句。如下:
var name = "windows";
var obj = {
name: "obj",
fun: function () {
var that = this; // 这里的this是指向obj的
return function(){
console.log(that.name);
}
}
}
obj.fun(); // 结果:ƒ (){console.log(this.name);}
obj.fun()(); // 结果:obj
// 原因:在函数返回来之前,我们通过that变量获取到了指向obj的this
// 所以结果是obj中的name的值。
6)对象里的方法返回箭头方法
var name = "windows";
var obj = {
name: "obj",
fun: function () {
return () => {
console.log(this.name);
}
}
}
obj.fun(); // 结果:() => {console.log(this.name);}
obj.fun()(); // 结果:obj
// 原因:箭头函数的this指向父级作用域,
// 箭头函数的父级是function,function会形成独立的作用域
// 而function作用域中的this指向obj,所以箭头函数的this就指向了obj
3.构造函数里的方法
var name = "windows";
function Person() {
this.name = "constructor";
this.fun1 = function () {
console.log(this.name); // 结果:constructor
};
this.fun2 = () =>{
console.log(this.name); // 结果:constructor
};
}
var p = new Person();
p.fun1(); // 结果:constructor
p.fun2(); // 结果:constructor
// 构造函数里的普通方法this指向构造函数new后的实例
// 箭头函数的this是父级作用域,父级是Person,Person是函数有自己的作用域且内部this指向自己
// 所以箭头函数的this就是指向person的
4.挂在到原型上的方法
var name = "windows";
function Person() {
this.name = "constructor";
this.fun1 = function () {
console.log(this.name); // 结果:constructor
};
this.fun2 = () =>{
console.log(this.name); // 结果:constructor
};
}
Person.prototype.fun3 = function() {
console.log(this.name);
};
Person.prototype.fun4 = () => {
console.log(this.name);
}
var p = new Person();
p.fun3(); // 结果:constructor
p.fun4(); // 结果:windows
// 原因:fun3()挂在到原型上的普通方法的this指向构造函数new的实例
// 原因:fun4()挂在到原型上的箭头函数this取决于上下文的作用域,
// fun4()是在全局下挂载到Person的原型上的,所以this指向window