this

2019年3月9日 中雨 14°C~17°C
广州持续下来很久很久的雨,一个星期?两个星期?忘了,又加上回南天,衣服不干,emmmm...

一、this的用法

this是函数运行时,在函数体内自动生成的一个对象,只有在函数体内部使用。

function test(){
   this.x = 1;
}
//函数test运行时,内部会自动生成一个this对象可以使用

函数的不同使用场合,this有不同的值。总的来说,this是函数运行时所在的环境对象

this的用法

1. 纯粹的函数调用

全局调用,函数最常用的方法,此时this代表全局对象。

var x = 1;
function test(){
  console.log(this.x);
}
test();    //1
2.作为对象的调用方法

函数可以作为对象的方法来被调用,此时this指向这个对象。

function test(){
  console.log(this.x)
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m();         //1
3.作为构造函数调用

通过构造函数,可以生成一个新的对象。这是,this指向这个新的对象。

var x = 2;
function test(){
  this.x = 1;
}
var obj = new test();
x   // 2
obj.x  //1;
4. apply调用

apply()是函数的一个方法,作用是改变函数的调用对象,它的第一个函数就表示改变后调用这个函数的对象。此时this指的就是这第一个参数。

var x = 0;
function test() {
  console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply();   //0

apply()的参数为空时,默认调用全局对象,因此,运行结果为0,this指向全局对象。
如果:

obj.m.apply(obj);    //1

运行结果变成了1,this指向对象obj;

二、this的原理

1. 由来
var obj = {
  foo: function() { console.log(this.bar)},
bar: 1
}

var foo = obj.foo;
var bar = 2;

//写法一
obj.foo();  // 1

//写法二
foo();    // 2

**this指的是函数运行时所在的环境,对于obj.foo,foo运行在obj环境,所以this指向obj,对于foo()来说,foo运行在全局环境,所以this指向全局环境。
函数的运行环境是怎么决定的?

2. 内存的数据结构
var obj = { foo: 5};

上面代码将一个对象赋值给变量obj,①JavaScript引擎会先在内存里面生成一个对象{ foo: 5},② 然后把这个对象的内存地址赋值给变量obj。

所以,变量obj是一个地址,如果要读取obj.foo,引擎会先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

原始的对象以字典结构保存,每一个属性名称都对应一个属性描写对象。如上例子foo属性,实际上是以下面的形式保存:

{
  foo: {
    [[value]]: 5
    [[writable]]: true
    [[enumerable]]: true
    [[configurable]]: true
  }
}

foo属性的值保存在属性貌似对象的value属性里面。

3. 函数

上面讲到对象的属性的值是一个值,二属性的值也可能是一个函数。

var obj = { foo: 5};
var obj = { foo: function(){} };

这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。
其实思路和上面的一样,只不过多了一个步骤:①引擎会将函数单独保存在内存中,②然后在内存里生成一个对象,对象的foo属性的value值是函数的内存地址,③将对象赋值给obj

var f = function() {};
var obj = {f : f};

f();   //单独执行

obj.f();    //obj环境执行
4. 环境变量

在函数体内部,可以引用当前环境的其他变量

var f = function() {
  console.log(x);
}

//函数体的变量x,由运行环境提供

由于函数可以在不同的运行环境中执行,this被设计于在函数体内部,指代函数当前的运行环境(context)。

var f = function() {
  console.log(this.x);
}

//this.x 指当前运行环境的x
var f = function() {
  console.log(this.x);
}
var x = 1;
var obj = {
  f: f,
  x: 2
}


f()   // 1, f()在全局环境执行

obj.f()   //2

三、this的指向形式(4种)

(1)一般函数,this指向全局对象window;
(2)在严格模式下“use strict”,为undefined;
(3)对象的方法里调用,指向该方法的对象;
(4)构造函数里的this,指向创建出来的实例

四、改变this的指向形式

.call()

call(thisScope,arg1,arg2,arg3...)
thisScope为新的指向

.apply()

.apply(thisScope,[arg1,arg2,arg3...])
两个参数,thisScope为新的指向

bind()

bind(thisScope,arg1,arg2,arg3...)
改变this的指向,返回的是函数,还需调用,而call()和apply()是改变this的指向并执行调用该函数

2019年3月8日 小雨
准备换工作之际,在几乎毫无准备的情况下,去面试了一家公司,面试官提到了怎样改变this的指向,我答不出。
于是去翻了阮一峰大神的博客,
JavaScript的this用法http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html
JavaScript的this原理http://www.ruanyifeng.com/blog/2018/06/javascript-this.html
还有看了一篇简洁的总结
https://www.jianshu.com/p/c415530030a9

你可能感兴趣的:(this)