this关键字总结

this 关键字

this可以用在构造函数之中,表示实例对象。除此之外,this还可以用在别的场合。但不管是什么场合,this都有一个共同点:它总是返回一个对象。简单说,this就是属性或方法“当前”所在的对象

由于函数可以在不同的运行环境执行,有时候函数我们希望在函数体内部当前环境下运行,但是有时候不指定环境的话,就会在windows环境下运行,就不是我们所希望的情况,所以需要有一种机制,能够在函数体内部获得当前的运行环境。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境

例如:

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

var x = 1;
var obj = {
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

第一个 f() 输出为1,this.x指向全局环境的x,因为全局定义了x=1 所以第一个输出为1
第二个 obj.f() 指定了运行环境 this.x指向了 obj下的xobj下的x为2,所以输出为2
可以看出,指定的运行环境不同,输出的值就不同

使用场合

(1)全局环境
全局环境使用this,它指的就是顶层对象window

this === window // true

function f() {
  console.log(this === window);
}
f() // true

上面代码说明,不管是不是在函数内部,只要是在全局环境下运行,this就是指顶层对象window

(2)构造函数
构造函数中的this,指的是实例对象

var Obj = function (p) {
  this.p = p;
};

上面代码定义了一个构造函数Obj。由于this指向实例对象,所以在构造函数内部定义this.p,就相当于定义实例对象有一个p属性
下面创建一个实例对象o,并给了属性值为Hello World!

var o = new Obj('Hello World!');
o.p // "Hello World!"

所以就会输出Hello World!

(3)对象的方法
如果对象的方法里面包含thisthis的指向就是方法运行时所在的对象。该方法赋值给另一个对象,就会改变this的指向。

var obj ={
  foo: function () {
    console.log(this);
  }
};
obj.foo()     // obj

下面这几种用法,就会改变this的指向

情况一
(obj.foo = obj.foo)()   // window
情况二
(false || obj.foo)()   // window
情况三
(1, obj.foo)()       // window

上面的情况就把obj.foo含义改变了,此时的obj.foo就是一个具体的值了,就不是指定环境了,所以运行环境就是windows了

如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层。下面的例子:

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined

为什么会undefined呢?
因为a.b.m方法在a对象的第二层,就是在a下面的b里面,该方法内部的this不是指向a,而是指向a.b,但是Hello在a下面,所以找不到,就打印undefined
如果要打印,就要将p: 'Hello',移一下位置变成:

var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

这样Hello就在b下面了,就可以打印了

使用注意点

避免多层 this
由于this的指向是不确定的,所以切勿在函数中包含多层的this
例如:

var o = {
  f1: function () {
    console.log(this);
    var f2 = function () {
      console.log(this);
    }();
  }
}

o.f1()
// Object
// Window

这样的this,第一层指向o,第二层就指向了windows
解决办法就是用一个变量thatthis接收一下,里面的that固定指向外层的this,这样内层的this就不会乱指了。

var o = {
  f1: function() {
    console.log(this);
    var that = this;
    var f2 = function() {
      console.log(that);
    }();
  }
}

o.f1()
// Object
// Object

绑定 this 的方法

JavaScript 提供了callapplybind这三个方法,来切换/固定this的指向。

Function.prototype.call()

函数实例的call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数,利用f.call(obj)这样就可以指定函数的作用域为obj
例如:

var obj = {};

var f = function () {
  return this;
};

f() === window // true
f.call(obj) === obj // true

call方法的参数,应该是一个对象。如果参数为空、nullundefined,则默认传入全局对象。
例如:

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456

a.call()
a.call(null)
a.call(undefined)
三种返回的值都为123,没有区别,并且this指向都为windows
a.call(window) 这个指定了运行环境为windows,所以输出为123
a.call(obj) 同理,这个指定了运行环境为obj,所以输出为456

Function.prototype.apply()

apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数,使用格式如下:

func.apply(thisValue, [arg1, arg2, ...])

apply方法的第一个参数也是this所要指向的那个对象,如果设为nullundefined,则等同于指定全局对象。第二个参数则是一个数组,该数组的所有成员依次作为参数,传入原函数。原函数的参数,在call方法中必须一个个添加,但是在apply方法中,必须以数组形式添加
例如:

function f(x, y){
  console.log(x + y);
}

f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2

call就是一个一个添加,apply是以数组形式添加

Function.prototype.bind()

bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
例子如下:

var counter = {
  count: 0,
  inc: function () {
    this.count++;
  }
};

var func = counter.inc.bind(counter);
func();
counter.count // 1

正常不用bind()的话,counter.inc()就被作为值赋给func了,这样运行环境就不对了,
counter.inc.bind(counter)这样就把inc里面的this运行环境绑定在counter 了,就不会出错了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值