学习 this 记录

this 原理

首先,要知道的是 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.fnfn调用的都是同一个函数,但结果却不同,这就是咱们上面说的 this 是根据运行时所在环境不一样致使的,对于 obj.fn 来讲,fn 是运行来 obj 环境的,因此this 指向 obj,对于 fn 来讲是运行在全局的,所以 this 指向的是全局,也就是 window数据结构

那为何 obj.fn() 就是在 obj 环境运行的,而一旦 var fn = obj.fn 就变成全局环境了呢?下面让咱们一点点揭开 this 的神秘面纱。闭包

1. 内存的数据结构

javascript 之全部有 this,是和内存结构有关系的。app

var obj = {fn:5}
复制代码

以上代码,将一个对象赋值给变量 obj,在 javascript 的 引擎中会先在内存中,生成一个对象 { fn:5},而后在将这个对象的地址赋给变量 obj函数

就是说,变量 obj 只是存了一个地址,若是要进行取读操做 obj.fn,那引擎是先从 obj 拿到内存地址,而后在从该地址读出原始对象,而后返回它的 fn 属性。ui

原始的对象以相似于字典结构的状态保存,每个属性名都对应一个属性描述对象。拿上面的那个例子的 fn 属性来看this

注意!fn 属性的值是保存在属性描述对象的 value 属性里面spa

2. 函数

属性值不是一个函数的时候很清晰,那若是属性的值是一个函数呢?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
复制代码

3. 环境变量

因为 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 使用

this 是 javascript 中的一个关键字。
它是在运行时,在函数体内自动生成的一个对象,所以只能在函数体内使用

下面让咱们直截了当的来看下 this 的几种使用方式

1. 函数调用

函数的一般用法,这种属于全局调用,所以这时 this 就表明者全局对象

var x = 1;

function fn(){
    console.log(x); // 变量 x,这时是全局的变量 x
}
fn(); //1
复制代码

2. 匿名函数的使用

匿名函数执行时,this 表明者全局

var x = 1;
var fn = function(){
    console.log(this.x);
}
fn(); // 1

//经常使用闭包式匿名函数

(function(){
    console.log(this.x)
})() //1
复制代码

3. 做为对象调用

当函数做为对象调用的时候,此时的 this 是这个上级对象

function fn(){
    console.log(this.x); //this 指向 obj
}
var obj = {
    x:1,
    m:fn
}    
obj.m(); // 1 
复制代码

4. 构造函数使用

当经过构造函数,生成一个新对象时,此时 this 是指这个新对象

function Fn(){
    this.x = 1; 
}
var x = 2; 
var obj = new Fn();
obj.x // 1
复制代码

5. apply / call 时调用

apply/call 是函数的一个方法,主要就是用来改为函数调用的,第一个参数就是要改变的对象,所以,this 就是指这第一个参数,若是第一个参数无,那 this 就表明者全局

var x = 1;
function fn(){
    console.log(this.x);
}
var obj = {
    x: 2,
    m:fn
}

obj.m.apply(); // 1
复制代码

更多详情请移步 阮一峰老师博文

相关文章
相关标签/搜索