javascript中this的指向问题
一. 全局作用域或者普通函数中 this 指向全局对象 window。
①全局作用域
console.log(this) //window
②普通函数(方法调用,是window对象调用的)
function fun1 () {
console.log(this)//window
}
fun1() //相当于window.fun1()
//普通函数的嵌套
var a=11
function fun3(){
console.log(this.a)//11 因为是普通函数所以this指向window
this.d=22;//因为this指向window,相当于在window对象添加一个d属性
function fun31(){
console.log(this.d);//22 因为是普通函数所以this指向window
};
fun31();
}
fun3();//相当于window.fun3()
//和上面普通函数的嵌套进行区分,构造函数嵌套普通函数
var y=11
function Test(){
console.log(this)//Test 实例
this.y=22;
let c=function(){
console.log(this.y);//11 window
};
c();//window.c()
}
new Test();
③自执行函数this指向window
(function(){
console.log(this)//window
})();
④定时器(setTimeout setInterval)环境this指向window
setTimeout(function () {//相当于window.setTimeout()
console.log(this);//window
},1000);
⑤在普通对象里面this指向window
var qq={
a:this
}
console.log(qq)//{a:Window}
console.log(qq.a)//Window
二. 在调用方法时谁调用的this就指向谁
①对象中方法的调用,this指向对象本身
var obj1 = {
fun4: function () {
console.log(this)//obj1
}
}
obj1.fun4()
//事件绑定
var btn = document.querySelector(".btn1")
btn.onclick = function () {
console.log(this) // btn1
}
//事件监听
var btn = document.querySelector(".btn2")
btn.addEventListener('click', function () {
console.log(this) //btn2
})
三.在构造函数或者原型对象中 this 指向构造函数的实例
这里需要说一下在使用构造函数创建实例时构造函数做了哪些工作(很重要):
1、创建一个空对象
2、使 this 指向这个空对象
3、执行构造函数为这个对象添加属性
4、返回此对象
①不使用new时(相当于普通函数)this指向window
function Person1(name) {
console.log(this); // window
this.name = name;
}
Person1('jqy')
②使用new时 this指向构造函数的实例
function Person2() {
console.log(this) //people
s = this//不声明 默认为全局变量
}
var people = new Person2()
console.log(s === people) //true
console.log(s === Person2) //false
③原型对象方法中的this指向实例对象
function Person4() {}
Person4.prototype.sayHi = function () {
console.log(this);//per4
};
var per4 = new Person4();
per4.sayHi();
四.箭头函数中的this指向其外层作用域的this
箭头函数本身是没有 this 的。
//①
var obj3 = {
foo() {
console.log(this);
},
bar: () => {
console.log(this);
}
}
obj3.foo() // {foo: ƒ, bar: ƒ}
obj3.bar() // window,指向外层 obj3 对象作用域
//②
var obj4={
fn:function(){
console.log(this);//obj4
var f=() => {
console.log(this); //相当于上面2行 obj4
setTimeout(function() { //相当于window.setTimeout()
console.log(this);//window
});
}
f();
}
}
obj4.fn();
//③ 区别与②
var obj5={
fn:()=>{
console.log(this);//window
var f=() => {
console.log(this);//window
setTimeout(function() {
console.log(this);//window
});
}
f();
}
}
obj5.fn();
//如果有多级箭头函数嵌套()=> () => () => this.a this指向第一个箭头函数的上一级对象。
//④箭头函数练习
var a = 20;
var obj6 = {
a: 10,
b: function() {
console.log(this);
console.log(this.a);
},
b1:this.a,
c:{
a:50,
b:20,
fn:function(){
console.log(this.a);
}
},
d: () => {
console.log(this.a);
},
e: function() {
return () => {
console.log(this.a);
}
}
}
obj6.b();//obj6 10 对象里面的方法谁调用指向谁
console.log(obj6.b1);//20 在对象{}里面,this指向window
console.log(obj6.c.b);//20 对象中 this 指向window
obj6.c.fn();//50 fn() 中的 this 指向对象c,区分下面的方法
var f=obj6.c.fn;
f();//20 指向window,window.f()
obj6.d();//20 箭头函数没有自己的this,它只会从自己的作用域链的上一层继承this。 this 指向window
obj6.e()();//10 this指向obj6,相当于obj6调用obj6.e()返回的函数
//⑤例外:当构造函数中遇到retrun,如果返回值是一个对象,那么this指向的就是那个返回的对象
//否则this指向构造函数的实例。拿下面举例:
//在构造函数中使用 return 本身就有点扯,因为构造函数在 new 实例时本身会返回一个对象,如
//果又 return 一个对象的话就会覆盖构造函数本身返回的对象。所以下面问题的关键就是如果在
//构造函数return对象,那么这个对象会覆盖默认返回的对象,否则如果不自己主动return或者
//return非对象数据则返回默认对象。
function Fn(){
this.user = '小明';
return {
age:18,
name:'qaz'
};
}
var a = new Fn();
console.log(a);//{age: 18, name: "qaz"}
console.log(a.user); //undefined
function Fn1(){
this.user = '小明';
return 1;
}
var a1 = new Fn1();
console.log(a);//fn {user: "小明"}
console.log(a1.user); //小明