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:( ...
随机推荐
- mysql-connector-python 源码安装
一.下载mysql-connector-python的源码包: 下载页面: https://dev.mysql.com/downloads/connector/python/ 我这下载的是mysql- ...
- Tomcat7中开启gzip压缩功能的配置方法
使用gzip压缩可以减少数据传输大小,加快网页加载速度.很多大站都开启了gzip压缩,不过也有很多网站并没有开启gzip压缩,上次看了一篇文章说开启gzip压缩后对搜索引擎不友好,但从带宽和流量的角度 ...
- Struts2初学 Struts.xml详解二
A.使用继承实现设置全局视图 package节点中还可以设置全局的视图,如: <global-results> <result name="e ...
- 李洪强漫谈iOS开发[C语言-053]-小结
/* 已经学习过的C语言语法 01 基本C程序结构 int main (void) int main(int argc,char *arv){...} 02 基本语句(输入输出) 基本头文件: #in ...
- PyCharm 在django程序中单独运行py文件
使用PyCharm开发django程序,发现如果不在命令行而在IDE的django项目中直接运行django程序,发现报错,程序如下: def main(): from people.models ...
- The 14th UESTC Programming Contest Final B - Banana Watch 预处理、前缀和
B - Banana Watch Time Limit: 1000/1000MS (Java/Others) Memory Limit: 262144/262144KB (Java/Other ...
- mongdb 慢查询
查看mongodb慢查询 赶紧打开服务器爸爸,开慢查询,看下耗时500ms以上的都是些啥: db.setProfilingLevel(2,500) 看下最近的10条具体的慢查询指令: db.syste ...
- c配置库ccl使用小结
配置文件为key=value键值对形式 下载与安装 库文件下载:ccl-0.1.1.tar.gz 安装: tar -zxvf ccl-0.1.1.tar.gz cd ccl-0.1.1 ./con ...
- 阿里云ecs开启x11图形化桌面
阿里云帮助文档:https://www.alibabacloud.com/help/zh/faq-detail/41227.htm 安装云服务器 ECS CentOS 7 图形化桌面 以安装 MATE ...
- TensorFlow基础笔记(6) 图像风格化实验
参考 http://blog.csdn.net/wspba/article/details/53994649 https://www.ctolib.com/AdaIN-style.html Ackno ...