JS中的this的指向是个令人头疼的问题,看了好多博客,自己总结一下大家也看一下:
什么是this?
this是JavaScript语言的一个关键字,它是函数运行时自动生成的一个内部对象,只能在函数内部调用
最重要的一句话:this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁最终调用函数,this就指向谁。
情况一:所有在全局作用域中定义的变量和函数都是window对象的属性和方法,下面两种代码效果是一样的,window对象调用a(),所以this就指向window对象。
function a(){
var user = "cat";
console.log(this.user); //undefined
console.log(this); //Window
}
a();//this-->window,全局作用域下调用
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
window.a();//this-->window,全局作用域下调用
情况二:o对象调用fn(),所以this指向o对象,这里需要强调一点:我们创建的o对象其实是window对象的属性,所以可以通过window对象来引用o对象。
var o = {
user:"追梦子",
fn:function(){
console.log(this.user); //追梦子
}
}
window.o.fn();//this-->o,o调用
情况三:如果存在对象的嵌套,那么this对应的函数如果被上一级的对象所调用,那么this指向的就是上一级的对象。
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
}
}
}
o.b.fn();//this-->b,b调用
情况四:
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //undefined
console.log(this); //window
}
}
}
var j = o.b.fn;
j();//this-->window
虽然函数fn是被对象b所引用,但是在将fn赋值给变量j的时候并没有执行所以最终指向的是window。
情况五:函数作为构造函数,用new 关键字调用时,this指向new出来的对象
function func(){
console.log(this);
}
var obj = new func();this-->obj
情况六:函数作为window内置函数(setInterval setTimeout等)的回调函数使用,this指向window
function func() {
console.log(this);
}
setTimeout(func,1000);//this-->window
情况七:全局函数在严格模式下this默认指向undefined
function foo() {
'use strict';
console.log(this);
}
foo();//this-->undefined
情况八:箭头函数没有自己的this,不绑定this,它的this是继承而来的,指向定义时所在的对象
var obj = {
say: function () {
setTimeout(() => {
console.log(this);// this继承自obj,故this指向obj
});
}
}
obj.say();
var obj = {
say: function () {
var f1 = () => {
console.log(this); // this指向定义时所在对象obj
setTimeout(() => {
console.log(this); // this继承自f1
},1000)
}
f1();
}
}
obj.say()
var obj = {
say: function () {
var f1 = function () {
console.log(this); // this指向window, f1调用时,没有宿主对象,默认是window
setTimeout(() => {
console.log(this); // this继承自f1,故指向window
})
};
f1();
}
}
obj.say()
情况九:
function fruits() {}
fruits.prototype = {
color: "red",
say: function() {
console.log("My color is " + this.color);
}
}
var apple = new fruits;
apple.say(); //My color is red
但是如果我们有一个对象banana= {color : "yellow"} ,我们不想对它重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:
banana = {
color: "yellow"
}
apple.say.call(banana); //My color is yellow
apple.say.apply(banana); //My color is yellow
所以,可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 object 没有某个方法(本栗子中banana没有say方法),但是其他的有(本栗子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。