首先,要知道的是
this
是指函数当前的运行环境(上下文)。javascript
咱们都知道 this 是函数运行时所在的环境,但咱们不知道是函数的运行环境究竟是怎么决定的。java
var obj = {
fn:function(){
console.log(this.title);
},
title:"Hello"
}
var fn = obj.fn;
var title = "Hi";
obj.fn() //"Hello"
fn() //"Hi"
复制代码
上面的例子中,obj.fn
和 fn
调用的都是同一个函数,但结果却不同,这就是咱们上面说的 this 是根据运行时所在环境不一样致使的,对于 obj.fn
来讲,fn
是运行来 obj
环境的,因此this
指向 obj
,对于 fn
来讲是运行在全局的,所以 this
指向的是全局,也就是 window
。数据结构
那为何 obj.fn()
就是在 obj
环境运行的,而一旦 var fn = obj.fn
就变成全局环境了呢?下面让咱们一点点揭开 this
的神秘面纱。闭包
javascript 之全部有 this,是和内存结构有关系的。app
var obj = {fn:5}
复制代码
以上代码,将一个对象赋值给变量 obj
,在 javascript
的 引擎中会先在内存中,生成一个对象 { fn:5}
,而后在将这个对象的地址赋给变量 obj
。函数
就是说,变量 obj
只是存了一个地址,若是要进行取读操做 obj.fn
,那引擎是先从 obj
拿到内存地址,而后在从该地址读出原始对象,而后返回它的 fn 属性。ui
原始的对象以相似于字典结构的状态保存,每个属性名都对应一个属性描述对象。拿上面的那个例子的 fn
属性来看this
注意!fn 属性的值是保存在属性描述对象的 value 属性里面spa
属性值不是一个函数的时候很清晰,那若是属性的值是一个函数呢?3d
var obj = { fn: function(){}};
复制代码
当对象的属性值是函数的时候,javascript
引擎会单独把函数保存在内存中,而后再将函数的地址赋值给 fn
属性的属性描述对象的 value
属性上。
因为函数是单独的一个值,因此它能够在不一样的环境 ( 上下文 ) 中运行。
var fn = function(){
console.log(this.age);
};
var obj = {
fn: fn,
age: 5
};
var age = 10;
//单独运行时
fn(); //10
//在obj中运行时
obj.fn(); // 5
复制代码
因为 javascript 容许函数体内,引用当前环境的其余变量,而变量是有当前的运行环境提供的,那么因为函数是能够在不一样的运行环境中执行,那就须要一种机制,一种可以在函数体内部得到当前运行环境。so,这时 this 出现了,它的目的就是在函数体内部,指向函数当前的运行环境。
function fn (){
console.log(age); //由运行环境提供
}
var age= 10";
fn(); //10
复制代码
以上代码中的 age 就由该函数运行时所在的环境提供。
再看,下面的例子
function fn(){
console.log(this.xx);
}
var xx = 10;
var obj = {
fn: fn,
xx: 100
}
//单独运行时
fn()//10
//在obj中运行时
obj.fn()//100
复制代码
this.xx
指向运行时所在的环境的 xx。fn()
单独运行时,this.xx
指向全局环境的 xx。obj.fn()
运行时,则 this.xx
指向的是 obj
环境的 xx。如今,咱们回到文章中最开始提出的问题,obj.fn()
是经过 obj
找到的 fn
,因此就是在 obj
环境执行,一旦 var fn = obj.fn
,则 变量 fn
就直接指向了函数自己,因此 fn()
就变成了全局环境执行。
注意!不要忘记,当对象里的属性名的值是一个函数的时候,这时,javascript 引擎就报函数单独保存在内存中,而后把函数地址给了 属性名的属性描述对象的value上。
this 是 javascript 中的一个关键字。
它是在运行时,在函数体内自动生成的一个对象,所以只能在函数体内使用
下面让咱们直截了当的来看下 this 的几种使用方式
函数的一般用法,这种属于全局调用,所以这时 this
就表明者全局对象
var x = 1;
function fn(){
console.log(x); // 变量 x,这时是全局的变量 x
}
fn(); //1
复制代码
匿名函数执行时,this
表明者全局
var x = 1;
var fn = function(){
console.log(this.x);
}
fn(); // 1
//经常使用闭包式匿名函数
(function(){
console.log(this.x)
})() //1
复制代码
当函数做为对象调用的时候,此时的 this
是这个上级对象
function fn(){
console.log(this.x); //this 指向 obj
}
var obj = {
x:1,
m:fn
}
obj.m(); // 1
复制代码
当经过构造函数,生成一个新对象时,此时 this
是指这个新对象
function Fn(){
this.x = 1;
}
var x = 2;
var obj = new Fn();
obj.x // 1
复制代码
apply/call
是函数的一个方法,主要就是用来改为函数调用的,第一个参数就是要改变的对象,所以,this 就是指这第一个参数,若是第一个参数无,那 this
就表明者全局
var x = 1;
function fn(){
console.log(this.x);
}
var obj = {
x: 2,
m:fn
}
obj.m.apply(); // 1
复制代码
更多详情请移步 阮一峰老师博文