js 中 this 的指向问题
高程上的大前提:
1、this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this 等于window,而当函数被作为某个对象的方法调用时,this 等于那个对象;不过,匿名函数的执行环境具有全局性,因此其this 对象通常指向window。
2、每个函数在被调用时都会自动取得两个特殊变量:this 和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量;
总结:
1、在事件处理程序中,事件绑定在哪个元素身上,this 就指向谁;分析戳这里;
2、在方法调用(如果某个对象的属性是函数,这个属性就叫方法,调用这个属性,就叫方法调用)中,执行函数体的时候,作为属性访问主体的对象和数组便是其调用方法内 this 的指向。(通俗的说,调用谁的方法 this 就指向谁;)
3、普通函数执行里的 this 都是 全局对象,非严格模式下浏览器端指的是 window(严格模式下 undefined,因为全局变量对象里没有定义this),因为都是在全局环境下执行的;
4、任意函数里如果嵌套了 函数,那这个时候 嵌套函数里的 this 在未指定的情况下,应该指向的是 window 对象(浏览器中非严格模式下,严格模式下返回 undefined ,因为嵌套函数里活动对象未指定 this);如果想在嵌套函数中继续用原来的 this 指向,需要保存下,比如 var self = this ,然后在嵌套函数中使用 self 变量,因为 this 不会传递;
这里加个案例:
var arr = [1, 2, 3];
arr.map(function() {
console.log(this);
});
你觉得这里 this 是 arr 对象么?
不是的,全局环境下,输出三个 window,你可能以为上面的理论错了,其实不是,map 作为 arr 对象的方法,在 map 函数里访问 this 当然是 arr 对象,而这里相当于在 arr.map 函数里又嵌套了一层函数,没指定的情况下,this 当然是 window,这里容易混淆,注意理解;
这里重写了默认的 map 方法,方便理解:
var arr = [1, 2, 3];
arr.map = function(fn) {
console.log(this); //输出 arr 对象
fn();
};
arr.map(function() {
console.log(this);//输出 window ,全局环境下
});
如果要把 map 里的 this 保存到嵌套的函数里:
var arr = [1, 2, 3];
arr.map = function(fn) {
fn.call(this); // 法一:把 this 作为参数传进去,替换了原来 fn 中的 this
var self=this; // 法二:保存下来,在嵌套函数里用
(function () {
console.log(self);
}());
};
arr.map(function() {
console.log(this);
});
这样就输出两次 arr 对象了,call 不会用点这里
5、通过构造函数创建对象,在调用构造函数之前就已经创建了新对象,并将构造函数的作用域赋给了新对象,因此构造函数里的 this 指向的就是这个新对象;
6、with 语句并没有改变 this 的指向,不过表现确实有点奇怪,看截图:

7、一些特殊情况,如:逗号运算符,赋值运算符
var name = "The Window";
var object = {
name: "My Object",
getName: function() {
return this.name;
}
};
object.getName(); //"My Object"
(object.getName)(); //"My Object"
(object.getName = object.getName)(); //"The Window",在非严格模式下
(object.getName, object.getName)(); //"The Window",在非严格模式下
第9行代码解释:
虽然加上括号之后,就好像只是在引用一个函数,但this 的值得到了维持,因为object.getName 和(object.getName)的定义是相同的。
根据 MDN ,圆括号运算符() 用来控制表达式中的运算优先级。所以书上说,没有改变 this,我觉得是说的过去的;
第10行代码解释:
代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是函数本身,所以this 的值不能得到维持,结果就返回了"The Window"。
我的理解是,赋值表达式返回了内存中的一个值,也就是函数本身,而不是原来方法的引用,所以 this 没有得到维持,结果返回了 window;
第11行代码解释:
同上,因为根据 MDN ,逗号操作符 也是返回最后一个操作数的值,也是函数本身,所以和上面一样;
按照这个逻辑的话,所有返回值操作的,都有可能去改变上面代码中的 this 值,都需要谨慎,譬如:
var a = {
func: function() {
return this;
}
};
function f(fn) {
console.log(fn());
}
f(a.func);//window
因为函数中的参数也是按照值传递的,在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量。
参考资料:
js 中 this 的指向问题的更多相关文章
- 理解js中this的指向
学习自原文 http://www.cnblogs.com/pssp/p/5216085.html后的一点小结(原文作者总结的很棒^_^)! 关于js中this的指向,在函数定义的时候还无法 ...
- js中this的指向
在js中this的指向对于新手来说一定是个难题,但是如果你真正理解了的话,也就没什么问题啦,下面就来讲讲this吧. JS中,this的值取决于调用的模式(调用对象),而JS中共有4种调用模式: 1. ...
- JS中的this 指向问题
我发现在对JS的学习中有很多朋友对this的指向问题还是有很大的误区或者说只是大致了解,但是一旦遇到复杂的情况就会因为this指向问题而引发各种bug. 对于之前学习过c或者是Java的朋友来说可能这 ...
- 轻松了解JS中this的指向
JS中的this指向一直是个让人头疼的问题,想当初我学的是天昏地暗,查了好多资料,看的头都大了,跟他大战了那么多回合,终于把它搞定个七八分,其实往往都是我们复杂化了,现在就让大家轻松看懂this的指向 ...
- js中改变this指向的call、apply、bind 方法使用
前言: 由于js 中this的指向受函数运行环境的影响,指向经常改变,使得开发变得困难和模糊,所以在封装sdk,写一些复杂函数的时候经常会用到this 指向绑定,以避免出现不必要的问题,call.ap ...
- js中 this 的指向
js中 this的指向一共存在3种地方: 1.全局的this; 2.构造函数的this; 3.call/apply; 一.全局的this: function test(){ this.d = 3;// ...
- 彻底理解js中this的指向,不必硬背。
首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然 ...
- 了解学习JS中this的指向
[转] 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问 ...
- JS中this的指向问题
JS中this的定义:this对象是在运行时基于函数的执行环境绑定的(通俗点来说就是:this代表当前函数属于哪个对象). this一般情况下都代表的是global对象,在浏览器中就是window对象 ...
- Js中的this指向问题
函数中的this指向和当前函数在哪定义的或者在哪执行的都没有任何的关系分析this指向的规律如下: [非严格模式]1.自执行函数中的this永远是window [案例1] var obj={ fn:( ...
随机推荐
- 分布式ID生成方案
系统唯一ID是设计一个系统的时候常常会遇到的问题,也常常为这个问题而纠结. 生成ID的方法有很多,适应不同的场景.需求以及性能要求.所以有些比较复杂的系统会有多个ID生成的策略. 0. 分布式ID要求 ...
- android自定义控件(1)-自定义控件属性
那么还是针对我们之前写的自定义控件:开关按钮为例来说,在之前的基础上,我们来看看有哪些属性是可以自定义的:按钮的背景图片,按钮的滑块图片,和按钮的状态(是开还是关),实际上都应该是可以在xml文件中直 ...
- 01、Windows Store APP 设置页面横竖屏的方法
在 windows phone store app 中,判断和设置页面横竖屏的方法,与 silverlight 中的 Page 类 不同,不能直接通过 Page.Orientation 进行设置.而是 ...
- ELK-“线上标准文档”——测试
Elasticstack官网:https://www.elastic.co 本文档仅限搭建过程参考,使用相关的文档,不在本文档讨论范围之内. 一切依据的核心即是Elasticstack官网. 查看支持 ...
- cloudera-manager-installer.bin不生成repo文件
[转] 运行cloudera-manager-installer.bin,并在后边增加参数使其不再在/etc/yum.repo.d/下生成cloudera-manager.repo文件 ./cloud ...
- SQL Server 2008 允许远程链接 解决方法
用户在使用SQL Server 2008远程链接时,可能会弹出如下对话框: 在链接SQL服务器时发生网络链接错误或特定实例错误.SQL服务器不存在或者链接不成功.请验证用户名是否正确或SQL服务器是否 ...
- nginx解析漏洞
一个比较老的漏洞了,但是今天在一个交流群里大佬们有那么一个案例.就深入学习了一下其原理. Nginx当检查url最后的文件名为脚本的时候,他就会把整个程序当作脚本来执行,否则就当作非脚本执行. 正确上 ...
- lua字符串对齐函数
最近要用到字符串对齐,开始只是一部分字符串,就直接加空格了,后来发现有很多, 于是写了个字符串对齐的函数. --功能:分割字符串 --参数:带分割字符串,分隔符 --返回:字符串表 function ...
- (译).NET4.X并行任务Task需要释放吗?
摘要:本博文解释在.NET 4.X中的Task使用完后为什么不应该调用Dispose().并且说明.NET4.5对.NET4.0的Task对象进行的部分改进:减轻Task对WaitHandle对象的依 ...
- RabbitMQ之主题(Topic)【译】
在上一节中,我们改进了我们的日志系统,替换使用fanout exchange仅仅能广播消息,使得选择性的接收日志成为可能. 虽然使用direct exchange改进了我们的系统,但是它仍然由他的局限 ...