黄金守则:

this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window而当函数被作为某个对象的方法调用时, this等于那个对象。

下面是一些相关实践:

------------------------------------------------->闭包相关的this<--------------------------------------------------------

我们知道,匿名函数的执行环境具有全局性,因此this对象通常指向window,但是由于闭包的编写方式不同,这一点可能不那么明显:

这是为什么呢?其实每个函数在被调用时,其活动对象都会自动获取两个特殊的变量:this和arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远不可能直接访问到外部函数中的这两个变量了。

不过下面这样改写,就可以做到了。

----------------------------------------------->函数相关的this<-----------------------------------------------------

先看一个最最简单的例子:

this当然会undefined,因为this的指向实际是指向它的调用的。实际上,前面这样说是不对的,谢小胡子的提醒呢。实际上这个undefined是整个函数的运行结果,函数并没有返回任何值,所以它才是undefined的~~~

下面还有两个特殊的情况,闭包中this的表现:

因为闭包立即执行,这相当于在全局的作用于下调用了函数,于是乎,可以看到,他就是指向了window了。

可是.......strict模式下的:

这就是闭包中使用严格模式的后遗症,它不让this指向全局作用域了呢。

这有个总结javascript中‘use strict’的资料,总结的挺好听明白的:http://www.web-tinker.com/article/20125.html

那么说了this是指向他的调用了,到底是怎么指向的呢,我们试试几个小例子,看看它的行为:

1.最普通的:

看吧,刚才还undefined呢,调用一下this就指向调用它的作用域了喔。

这个更印证了this指向调用他的作用域。

2.那我现在把函数嵌套一下试试看呢:

还是window喔,这里this是属于window喔,好像说也说不清楚,自己写写试试想想,体会体会喔。

3.上面基本上都是函数调用时候的情况,那下面我试一下函数引用,来看看会是什么样子呢,稍稍复杂些:

上面事实证明,引用函数是可以改变函数的执行作用域的,但是像之前的,调用函数是不会改变函数的执行作用域的呢:

事实证明条用函数是不会改变函数的执行作用域的(注意上面两段代码中me:后面的使用方式)。

这有道题目:

------------------------------------------------>构造函数中的this<----------------------------------------------------

1.下面我们先看看js中简单封装过程中用到的this:

上面实现的并不是严格的封装,但是从中我们可以看到this的作用。

2.别急,肯定还是有点有意思的事情的:

这里通过new创建了一个新的对象呢,并将这个对象通过this传入到了构造器中,这也就是为什么b的作用域跑到了a{}里面。

这是为什么呢?? 我们来来看new构造函数这种用法是怎么回事吧:

简单来看:

其实new的作用就是使this指向一个新建的对象,然后return this。

实际它的运行情况是这样的:

1 function Person (){
2 // var obj = new Object();
3 // this = obj;
4 alert(this); // new 出来的 Person 对象
5 // return this;
6 }
7 var person = new Person();

实际上js的实现是这样的:

1 function newOperator(Constr, args) {
2 var thisValue = Object.create(Constr.prototype); // (1)
3 var result = Constr.apply(thisValue, args);
4 if (typeof result === 'object' && result !== null) {
5 return result; // (2)
6 }
7 return thisValue;
8 }

在网上看资料的时候看到的,链接在这里:http://speakingjs.com/es5/ch17.html#_the_new_operator_implemented_in_javascript

--------------------------------------------->call和apply对this的影响 <------------------------------------------------------------

看例子:

这里this就指向String了。

上面这个例子就通过call(),把x,y,传到了函数中。

------------------------------------------------------->定时器(setTimeout,setInterval)中的this<--------------------------------------------------------------

先看最简单的:

这里面this就是指向window。

实际上因为setTimeout()和setInterval()发放根本就是window的,所以当然指向window了。

更加印证了上面所说的。

但其实是,setTimeout()就是会产生一个不符合常理的this。它会在一个独立的执行上下文中运行。结果就是,他就会使this关键字指向window。 mdn上有详细的解释:https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers.setTimeout

 myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
alert(arguments.length > 0 ? this[sProperty] : this);
}; myArray.myMethod(); // prints "zero,one,two"
myArray.myMethod(1); // prints "one"
setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 second
setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1.5 seconds
// let's try to pass the 'this' object
setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object"
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error

但是mdn上面 也提供了解决方法:

 myArray = ["zero", "one", "two"];
myArray.myMethod = function (sProperty) {
alert(arguments.length > 0 ? this[sProperty] : this);
}; setTimeout(alert, 1500, "Hello world!"); // the standard use of setTimeout and setInterval is preserved, but...
setTimeout.call(myArray, myArray.myMethod, 2000); // prints "zero,one,two" after 2 seconds
setTimeout.call(myArray, myArray.myMethod, 2500, 2); // prints "two" after 2.5 seconds

--------------------------------------------------------------->eval()中的this<---------------------------------------------------------------------------

直接调用eval():

直接调用eval()的话,this指向当前作用域的。('use strict'不用也是一样的)

下面展示了不直接调用的情况:

------------------------------------------------------->复杂情况中的this<--------------------------------------------------------

在查找资料的过程中,发现了一个总结的挺好的,复杂情况下this的优先级,贴过来收藏:

优先级 情景 this 的值 备注
1 new new出来的空 object  
  apply / call 传入的参数 并列第一,apply / call不能和 new 同时出现
new arr1.show.apply(“1”); // 报错
2 定时器 window  
3 事件 发生事件的元素  
4 方法 所有者  
5 其他(嵌套等) window || undefined 看是否为严格模式

注:不管如何修改this,this只会影响一层

例:

深入探究js中无所不在的this的更多相关文章

  1. 深入探究js中的隐式变量声明

    前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...

  2. 探究JS中的连等赋值问题

    一.引子 最近在看别人的博客时无意中看到一个这样的问题 var a = {n: 1}; var b = a; a.x = a = {n:2}; console.log(a.x); //undefine ...

  3. 探究JS中对象的深拷贝和浅拷贝

    深拷贝和浅拷贝的区别 在讲深拷贝和浅拷贝的区别之前,回想一下我们平时拷贝一个对象时是怎么操作的?是不是像这样? var testObj1 = {a: 1, b:2}, testObj2=testObj ...

  4. 浅解析js中的对象

    浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...

  5. 第22篇 js中的this指针的用法

    前面把js的相关知识总结了下,今天把js中的上下文的this,对于强类型语言,this的用法非常的单一,因为他们没有js特有的动态绑定. 首先看下面代码: function funcA() { thi ...

  6. js中的栈、堆、队列、内存空间

    栈(stack) .堆(heap). 队列(queue)是js的三种数据结构. 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存 ...

  7. 「中高级前端必须了解的」JS中的内存管理

    前言 像C语言这样的底层语言一般都有底层的内存管理接口,比如 malloc()和free()用于分配内存和释放内存. 而对于JavaScript来说,会在创建变量(对象,字符串等)时分配内存,并且在不 ...

  8. js中的this指针的用法

    首先看下面代码: function funcA() { this.name = "hello"; console.log(this.name); this.show = funct ...

  9. 5.0 JS中引用类型介绍

    其实,在前面的"js的六大数据类型"文章中稍微说了一下引用类型.前面我们说到js中有六大数据类型(五种基本数据类型 + 一种引用类型).下面的章节中,我们将详细讲解引用类型. 1. ...

随机推荐

  1. java: R文件重复

    导入eclipse工程到intellij里面, 然后出现各种错误, xxx.R文件重复, 各种资源id在R文件中找不到, 后来发现是intellij默认将整个项目以及gen文件夹作为源代码目录了, 在 ...

  2. 深入理解Memcache原理 [转]

    1.为什么要使用memcache 由于网站的高并发读写需求,传统的关系型数据库开始出现瓶颈,例如: 1)对数据库的高并发读写: 关系型数据库本身就是个庞然大物,处理过程非常耗时(如解析SQL语句,事务 ...

  3. SQL 订阅发布备注

    单个用户问题 use mastergodeclare @SQL varchar(max)set @SQL=''select @SQL=@SQL+';kill '+RTRIM(spid)from mas ...

  4. Oracle sys和system用户、sysdba 和sysoper系统权限、sysdba和dba角色的区别

    sys和system用户区别 1)最重要的区别,存储的数据的重要性不同 sys所有oracle的数据字典的基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行是至关重要的,由数据库自己 ...

  5. [PL/SQL] 如何规避异常ORA-01403

    如果mytable表中不存在 ID = 123 的数据,那么 SELECT Flag INTO flag FROM mytable WHERE ID = 123 将抛出异常ORA-01403 SELE ...

  6. uml大战需求分析阅读笔记01

    <<UML大战需求分析>>阅读笔记(1) 刚读了uml大战需求分析的第一二章,读了这些内容之后,令我深有感触.以前学习uml这门课的时候,并没有好好学,那时我认为这门课并没有什 ...

  7. CentOS7下GNOME桌面的安装

    1,搭建yum源仓库.(yum的配置文件在/etc/yum.repos.d目录) (详见http://www.cnblogs.com/zyh120/p/6020781.html) 2,列出yum仓库里 ...

  8. java 实现多个文件的Zip包的生成

    最近在项目中遇到多个文件的达成Zip包,由于对这块不熟,在网上找到一个,现在忘了找的谁的,如果您发现了,请告诉我你的链接,我指明出处 下面是相关代码: package run.utils; impor ...

  9. 最全的MySQL基础【燕十八传世】

    1.课前准备! 开启mysql服务:1).配置环境变量;2).net start mysql 将该sql文件导入到你的数据库中,以下所有操作都是基于该数据库表操作的!!! [此笔记是本人看着视频加上自 ...

  10. JSON 序列化和反序列化——JavaScriptSerializer实现

    一. JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据.您无法访问序列化程序的此实例.但是,此类公开了公共 API.因此, ...