蓝戒博客

  • 首页
  • 研发说
  • 架构论
  • 效能录
  • AI谈
  • 随笔集
智构苍穹
融合 AI、架构与工程实践,沉淀方法论,构建可持续的技术价值。
  1. 首页
  2. 研发说
  3. 正文

js中this指向问题全解析

2017年7月11日 5128点热度 0人点赞 0条评论

通常而言在JS中, this的值取决于调用的模式, 而JS中共有4中调用模式:
1.方法调用模式
当一个函数被保存为对象的一个属性时, 我们称它为一个方法, 当一个方法被调用时, this指向该对象, 如:

var obj = {
value: 1,
getValue: function() {
alert(this.value);
}
};
obj.getValue(); // 输出1, 此时的this指向obj

注意: 该模式中, this到对象的绑定发生在方法被调用的时候.

2、函数调用模式
当一个函数并非一个对象的属性时, 它被当作一个函数来调用, 此时的this指向全局对象(window), 如:

window.value = 1;
function getValue() { alert(this.value); }
getValue(); // 输出1, 此时的this指向window.

3、构造器调用模式
结合new前缀调用的函数被称为构造器函数, 此时的this指向该构造器函数的实例对象, 如:

function show(val) {
this.value = val;
};
show.prototype.getVal = function() {
alert(this.value);
};
var func = new show(1);
func.getVal(); // 输出1
alert(func.value) // 输出1
// 从上面的结果, 可以看出, 此时的this指向了func对象.

4、apply/call调用模式以及bind
apply和call方法可以让我们设定调用者中的this指向谁, 如:

var fun = function(str) {
this.status = str;
}
fun.prototype.getStatus = function() {
alert(this.status);
}
var obj = {
status: "loading"
};
fun.prototype.getStatus.apply(obj); // 输出"loading", 此时getStatus方法中的this指向了obj

5、特殊情况
setInterval和setTimeout中传入函数时,函数中的this会指向window对象。

var num = 0;
function Obj (){
this.num = 1,
this.getNum = function(){
console.log(this.num);
},
this.getNumLater = function(){
setTimeout(function(){
console.log(this.num);
}, 1000)
}
}
var obj = new Obj;
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//0  打印的为window.num,值为0

从上述例子中可以看到setTimeout中函数内的this是指向了window对象,这是由于setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. 这会导致这些代码中包含的 this 关键字会指向 window (或全局)对象。

但是在setTimeout中传入的不是函数时,this则指向当前对象,如下例:

var num = 0;
function Obj (){
this.num = 1,
this.getNum = function(){
console.log(this.num);
},
this.getNumLater = function(){
setTimeout(console.log(this.num), 1000)
}
}
var obj = new Obj;
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//1  打印的为obj.num,值为1

从以上两个例子可以看出,当在setTimeout中传入的参数为函数时,函数内部的this才会指向window对象。

当在setTimeout中传入了一个函数,若想要让this指向正确的值,可以使用的二种常用方法来使this指向正确的值:
1.将当前对象的this存为一个变量,定时器内的函数利用闭包来访问这个变量
如下:

var num = 0;
function Obj (){
var that = this; //将this存为一个变量,此时的this指向obj
this.num = 1,
this.getNum = function(){
console.log(this.num);
},
this.getNumLater = function(){
setTimeout(function(){
console.log(that.num); //利用闭包访问that,that是一个指向obj的指针
}, 1000)
}
}
var obj = new Obj;
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//1  打印的为obj.num,值为1

这种方法是将当前对象的引用放在一个变量里,定时器内部的函数来访问到这个变量,自然就可以得到当前的对象。

2.利用bind()方法

var num = 0;
function Obj (){
this.num = 1,
this.getNum = function(){
console.log(this.num);
},
this.getNumLater = function(){
setTimeout(function(){
console.log(this.num);
}.bind(this), 1000) //利用bind()将this绑定到这个函数上
}
}
var obj = new Obj;
obj.getNum();//1  打印的为obj.num,值为1
obj.getNumLater()//1  打印的为obj.num,值为1

bind()方法是在Function.prototype上的一个方法,当被绑定函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this。在这个例子中,在调用setTimeout中的函数时,bind方法创建了一个新的函数,并将this传进新的函数,执行的结果也就是正确的了
当然如果使用call或apply方法来代替bind方法,得到的结果也是正确的,但是call方法会在调用之后立即执行,那样也就没有了延时的效果,定时器也就没有用了,所以推荐使用上述两种方法来将this传进setTimeout和setInterval中。

ES6的箭头函数

此外,使用ES6的箭头函数可以确保this指向当前作用域的对象

var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return () => {
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "obj.name"

参考资料:

1.http://blog.csdn.net/babybk/article/details/51272790
2.http://www.jb51.net/article/102232.htm
3.http://www.cnblogs.com/long-long/p/6741083.html

标签: javascript this
最后更新:2025年9月12日

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

最新 热点 随机
最新 热点 随机
Gemma 4发布4天即遭"完全越狱",开源AI的安全与自由之争 一个文件让AI写代码不再"翻车":45K星的Karpathy指南火了 3秒克隆你的声音,30国语言自由切换!这款2B开源语音模型,正在重新定义AI配音 claude-mem:给 Claude Code 补上一块最关键的“长期记忆” 🔥 狂揽 51.5k Star!这款名为 GSD 的神器,专治 AI 写代码"越写幻觉越严重" Token 节省的神器 RTK:降 90%,适用 Claude Code、Codex、Cursor 等
Dan Koe:不想打工?用这套方法把兴趣变成收入开源AI 搜索代理 MiroThinker 1.7:当大家还在卷参数,它已经开始卷“查证能力”了停止无效努力:Dan Koe 深度长文,极致专注力,一套让你进入心流的终极方法论2026 AI 智能体革命:LangGraph 如何让你一个人活成一支队伍?AI 智能体爆发:从会生成到会行动,2026 年普通人如何抓住 AaaS 变现红利AI专用浏览器来了:比Chrome快10倍,Agent时代的基础设施正在重构
javascript中DOM0,DOM2,DOM3级事件模型解析 Rolldown:Rust 驱动的高性能打包器深度解析 Vibe Coding:当“写代码”变成“说需求” AngularJs指令全解析 Web Workers:释放浏览器多线程的魔力 信息系统架构的形与魂:理论、方法与前端实践
最近评论
渔夫 发布于 5 个月前(11月05日) 学到了,感谢博主分享
沙拉小王子 发布于 9 年前(11月30日) 适合vue入门者学习,赞一个
沙拉小王子 发布于 9 年前(11月30日) 适合vue入门者学习,赞一个
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8

COPYRIGHT © 2025 蓝戒博客_智构苍穹-专注于大前端领域技术生态. ALL RIGHTS RESERVED.

京ICP备12026697号-2