Javscript中this详解
一 宿主环境和javascript 引擎
- 宿主环境:一门语言在运行的时候需要一个环境,这个环境就是宿主环境,对于JavaScript来说宿主环境就是我们常说的浏览器,在这个浏览器里面提供了一些借口让javascript引擎可以和宿主环境对接;
- jacascript引擎才是真正执行代码的地方,常见的javascript引擎包括V8,javascript core,javascript引擎主要做了以下几件事情:一套与宿主环境相互联系的规则,javascript引擎内核,规定了基本javascript语法逻辑和命令,一组内置对象和API
- javascript不仅可以在浏览器里面运行,还可以在其他宿主环境,比如node.js
二 this详解
1 global this
1.1在浏览器里面,全局范围内,this等价于window对象(其实window对象也是Window构造函数的实例)
|
|
1.2 在浏览器中,在全局范围内,用var声明一个变量和给this window 设置属性是等价的
|
|
1.2.1 预解析对顶级对象window的属性的添加
|
|
1.2.2 用function声明函数和在全局用var 声明变量,或者函数体不用var声明变量,都是在给全局的window添加属性值
|
|
1.2.3 如果没有用var 声明,那么则不会进行变量提升,即使该变量也是隐式全局变量
|
|
1.3 在函数体内 ,(即使是函数体内的函数嵌套函数),没有var或者let声明的变量或者函数,就是在给全局this window添加属性;如果使用了var 或者 let声明变量,则不能被全局的this访问到;
|
|
2 function this
2.0 对于一个函数,有三种角色,普通函数,直接调用执行;构造函数,通过new调用;函数作为对象;
2.1 如果不是被new调用函数,
- 普通函数:直接执行函数体,那么函数体的this都是指代全局范围的this,代表window对象;
|
|
- 直接执行函数体的时候,如果使用了apply call 则代表改变了函数运行时的this指向,原先this默认指向的是其执行的上下文环境;语法 fn.apply( thisArg[, argsArray] ) 、 fn.call( thisArg[, arg1[, arg2[, …]]] ) 执行之后,this指向传入的第一个参数
|
|
2.2 函数作为构造函数:如果被new操作符调用函数体,那么函数体的this就变成了一个新的值,和global的this没有任何关系
|
|
2.3 接下来解释下new 操作符的作用,看下面的代码
|
|
2.3.1 解释new的作用,当以 new 操作符调用构造函数的时候,函数内部 发生以下变化:
函数内部会创建一个空的对象,将该对象的引用指向this;所以后期只能通过this给实例添加属性和方法;
属性和方法会被添加到this 引用的对象中;
新创建的对象的引用指向了this,最后返回this
2.3.2 new操作符的作用如下:
|
|
2.3.3 从原型的角度理解下 new操作符的作用
|
|
2.3.4 如果使用构造函数显式的返回基本数据类型(number string boolean null undefined)不会影响输出结果 ,返回引用类型 object 则不会再返回构造函数的实例对象的地址,而是返回该引用的地址;
|
|
2.3.5 new操作符每次调用的时候,在堆 (heap)内存中开辟一块内存空间,存储实例化对象的信息;如果有变量接受该对象的地址,那么 定义变量的时候会在栈(stack) 中开辟了一块空间存储变量名和引用地址 ;不同的变量指向不同的堆内存空间
|
|
2.4 如果函数体是对象的方法,那么此时的函数体里面的this就是指向的调用 该函数的对象;注意区分下面这两种情况
|
|
|
|
2.5 如果函数体是数组中的元素,那么函数作为数组的元素被调用的时候,指向数组,对于伪数组来书也是指向伪数组
|
|
|
|
this指向被调用的直接对象 ,被谁调用指向谁
|
|
总结:函数直接执行相当于被window调用,所以函数中的this指向window
2.5 javascript 中经常用的也就是事件的绑定,对应的事件处理函数中如果出现了this,那么这个this代表的所绑定的元素
|
|
2.6 setInterval(fn,time) setTimeout(fn,time) 中的this指向window;为什么呢?大家还记得 setInterval setTimeont都是window对象的属性吗?setInterval(fn,time) 等价于 window.setInterval(fn,time)其实是window调用了setInterval方法,所以其指向window ;
|
|
3 prototype this
原型里面的this指向,包括实例化的方法中的this指向:可以这么理解,它指向实例化的那个对象,但是,在找相应的属性的时候,它会顺着原型链一级级向上找,直到找到那个属性,如果没有找到,那么返回undefined;
这个其实也是函数独立调用还是被对象调用的情况
|
|
通过原型添加属性和方法:this会顺着对象的原型链一直往下找,直到找到该属性为止,如果找不到的话,那么返回undefined;原型里的this也是指向实例化的对象,this.foo就是顺着原型链一直找;
|
|
4
三 this总结
1 this永远指向函数运行的时候所在的对象,而不是被创建的时候所在的对象;
2 匿名函数或不处于任何对象中的函数指向window
3 如果是call apply with 指定的this是谁,就是谁,如果是普通的函数调用,函数被谁调用,this就指向谁
4 如果不是被new调用函数,那么函数体的this都是指代全局范围的this,代表window对象;
5 函数独立运行的时候,那么this指向其所在运行的环境;函数作为对象的方法被调用的时候,this指向调用该函数的对象
6 如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。
如果函数独立调用,那么该函数内部的this,则指向undefined;但是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。
严格模式下this指向
|
|
|
|