JavaScript - this指向

84 阅读3分钟

一、普通函数this指向 :

普通函数this指向函数最终被调用的对象;

注意:普通函数在 "use strict" 严格模式下,this不再指向window;

/*非严格模式下:*/
function fn(){
	console.log(this);
}
fn();//window 说明:当前调用相当于window.fn();调用,故this指向window

var fn = function(){
	console.log(this);
}
fn();//window 说明:当前调用相当于window.fn();调用,故this指向window

var obj = {
 	a: 1,
 	b: {
 		a: 2,
 		fn: function(){
 			console.log(this.a,this.b);
 		}
	},
	fn1: function(){
		console.log(this.a);
	}
}
obj.fn1(); //1 说明:this指向obj,当前函数被obj调用,故this指向obj
obj.b.fn(); //2,undefined 说明:指向obj.b,尽管对象被函数是被最外层的obj所调用,this指向的也只是它上一级的对象
var j = obj.b.fn;
j(); //undefined,undefined 说明:this指向windows,this永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的

二、箭头函数this指向:

捕获其所在(即定义的位置)上下文的this值,一直向上查询上下文的this值,无论是否严格模式; 注意:call(),apply(),bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响;

var fn = () => {
	console.log(this);
}
fn(); //window 说明:获取上下文的this值

var obj = {
	fn: () => {
		console.log(this);
		(() => {
			console.log(this);
		})();//window 说明:获取一直向上查询上下文的this值
	}
}
obj.fn(); //window 说明:获取上下文的this值

var obj = {
	say: function () {
		var fn = () => {
			console.log(this);
		};
		setTimeout(fn, 1000);
	}
};
obj.say(); //say 说明:获取上下文的this值

function Person() {
	setInterval(() => {
		console.log(this); //Person 说明:获取上下文的this值
	}, 3000);
	setTimeout(((arg) => {
		console.log(this, arg); //Person 100 说明:箭头函数绑定this没有作用this仍为Person,传参成功
    }).bind(undefined, 100), 3000);
}
var p = new Person();

三、构造函数this指向:

构造函数相当于复制了一份新的对象,this与被创建的新对象绑定。

this遇到return:

如果返回值是 原始值,那么this指向函数的实例,否则为 undefined

function fn(){
	this.user = '二狗子';
	return {};
	//return function(){};
	//return [];
	//return new Date();
	//return new Number();
}
var a = new fn();
console.log(a.user); //undefined 说明:this没有指向

function fn(){
	this.user = '二狗子';
	return null;
	//return undefined;
	//return "";
	//return 0;
	//return true;
	//return Symbol('a');
}
var a = new fn();
console.log(a.user); //二狗子 说明:this指向函数实例

四、DOM事件(函数非箭头函数):

this指向触发事件的元素

五、内联事件中的this指向:

onclick="console.log(this);" //DOM元素 说明:当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素
onclick="function()(console.log(this);)();" //window
onclick="function()('use strict';console.log(this);)();" //undefined

六、延迟器的this指向:

var obj = {
	abc: function(){
		setTimeout(()=>{
			console.log(this); //obj 说明:箭头函数,捕获其所在(即定义的位置)执行上下文的this值
		}, 2000);
		
		setTimeout(function() {
			console.log(this); //window 说明:无论在哪setTimeout里function的this是window
		}, 3000);
		
		setTimeout((function() {
			console.log(this); //obj 说明:经过bind绑定
		}).bind(this), 3000);
	}
}

七、绑定this(修改this指向):

function Person() {
	this.age = 10;
	setTimeout((function() {
		console.log(this.age); //10 说明:绑定this为Person
    }).bind(this), 3000);
    setTimeout((function() {
		console.log(this.age); //undefined 说明:绑定this为undefined
    }).bind(undefined), 3000);
	setTimeout(() => {
		console.log(this.age); //10 说明:箭头函数的this向上查找上下文的this值为Person
    }, 3000);
    setTimeout(((age) => {
    	this.age = age;
		console.log(this.age); //27 说明:箭头函数绑定this没有作用this仍为Person,传递参数成功
    }).bind(undefined, 27), 3000);
}
var p = new Person();

this绑定方法说明:

.call(对象, 参数1, ...,参数n);

.apply(对象, [参数1, ...,参数n]);

.bind(对象, 参数1, ...,参数n)();

说明:

三种方法的第一个参数都指定函数内部中this的指向函数执行时所在的作用域

都可以在函数调用时传递参数:call,bind方法需要直接传入,而apply方法需要以数组的形式传入。

call,apply方法是在调用之后立即执行函数,而bind方法没有立即执行,需要将函数再执行一遍。

八、总结:

  1. 通常this指向执行被调用的对象;
  2. 如果函数return的对象为原始值,那么this指向函数的实例,否则为undefined;
  3. 构造函数相当于复制了一份新的对象,this与被创建的新对象绑定;