在秋招面试中,由于对this指针的理解不够深刻,连掉两次大坑,所以在此整理一番关于this指针的一些概念理解及一些可能会掉的坑。
在JavaScript中this指针是执行上下文中的一个属性,会指向最后一次调用这个方法的对象。
全局环境
在全局环境中(即任何函数体外部的代码),this指针始终是指向全局对象。
函数环境
在函数环境中,函数的调用方式决定了this指针的指向,主要分四种:
1.函数调用模式,一个函数当它不作为一个对象的属性,而是直接作为函数来调用的时候,函数内部的this指针会指向全局对象。
var name = "全局";
function printName(){
var name = "函数";
console.log(this.name);
}
printName();//全局
//判断是函数调用还是方法调用是看执行的那一刻
var name = "全局";
var obj = {
name: "对象",
fn: printName;
}
function printName(){
var name = "函数";
console.log(this.name);
}
fn = obj.fn;
fn();//全局
2.方法调用模式,当一个函数作为一个对象的属性调用时,函数内部的this指针会指向这个调用的对象。
var name = "全局";
var obj = {
name: "对象",
fn: printName;
}
function printName(){
var name = "函数";
console.log(this.name);
}
obj.fn();//对象
//this指针是指向调用这个方法的对象,即离得最近的那个对象
var name = "全局";
var obj = {
name: "对象",
child: {
name: "子对象",
fn: printName;
}
}
function printName(){
var name = "函数";
console.log(this.name);
}
obj.child.fn();//子对象
//要注意箭头函数没有自己的this指针,函数会捕获其定义位置的上下文的this指针作为自己的this指针
var name = "全局";
var obj = {
name: "对象",
child: {
name: "子对象",
fn: () => {
var name = "函数";
console.log(this.name);
}
fn2: function(){
console.log(this.name);
}
}
}
obj.child.fn();//全局
obj.child.fn2();//子对象
3.构造器调用模式,当一个函数作为构造函数,用new来调用时,函数内部的this指针会指向创建返回的对象。
function createObj(){
this.name = "createObj";
}
var obj = new createObj();
console.log(obj.name)//createObj
4.apply,call,bind调用模式,这三个方法可以指定函数的this指针指向,但在使用上有所区别,请读者自行查阅其他资料。
var name = "全局"
obj = {
name: "对象"
}
function printName(){
console.log(this.name);
}
prinyName.call(obj);对象
setTimeout,setInterval环境
setTimeout,setInterval的回调函数中的执行环境与所在函数完全分离,因此其中的this指针总会指向全局。有三种办法的可以解决(1)用闭包原理,用一个变量保存当前函数this指针。(2)用bind方法改变this指针指向。(3)用箭头函数。
var name = "全局";var obj = {
name: "对象",
child: {
name: "子对象",
fn: function () {
var name = "函数";
setTimeout(function() {
console.log(this.name);
}, 0);
},
fn2: function () {
var name = "函数";
setTimeout(() => {
console.log(this.name);
}, 0)
};
}}
obj.child.fn(); //全局
//同样由于箭头函数没有自己的this指针
obj.child.fn2();//子对象