this的值

this关键字的指向是由它的调用方式决定的. 通常有两种环境调用this, 全局环境和函数环境. 函数环境中又有多种调用this的方法.
this不能在执行期间赋值. this就是函数运行时所在的对象(环境)

全局上下文

当全局环境执行代码时, 全局上下文(函数体外部)的中的this只有一种情况.

  • 无论是否在严格模式下,在全局执行上下文中(在任何函数体外部)this 都指代全局对象。

在浏览器中, 全局对象是window

console.log(this === window) //true

var a = 2
console.log(this.a === window.a) //true, 都为2

函数上下文

函数上下文中的情况就复杂多了.

函数常规调用中的this

非严格模式下的调用:

function fn() {
    return this
}
fn()    // 返回window对象
fn() === window //true

可以看到this指向是全局对象window.

  • 即非严格模式下, this指向全局对象

严格模式下的调用:

function fn() {
    return this
}
fn()    // 返回undefined
fn() === undefined //true

即:

  • 严格模式下, thisundefined

call, apply, bind方法中的this

  • this的实际值就是call函数的第一个参数. 也是apply, bind的第一个参数. 这三个函数之间略有差别.
function fn(){
  return this.a;
}
var obj = {a: 1}
fn()    //undefined, 应为没有为this指定值, fn()等同于fn.call(undefined)
fn.call(obj)    //1

当使用call方法绑定this值时, this就指向了obj对象. 因此this.aobj.a
apply方法和call类似, 不同的是, 若fn有参数, 则可以通过call的第二个及其之后的参数传入. 而apply是将fn的参数组成一个数组, 并作为apply的第二个参数传入.

function fn(x, y){
    return this.a + x + y
}
var obj = {a: 1}
fn.call(obj, 2, 3)      //1+2+3=6, 返回6
fn.apply(obj, [2,3])    //1+2+3=6, 返回6

bind方法就和上面连个方法有点区别了.

  • bind方法由于绑定this的值, 且bind只绑定一次.
function fn(){
    return this.a
}
var obj = {a: 1}
var o = {a: 2}
var f1 = fn.bind(obj)   
f1()    //1
var f2 = f1.bind(o)     
f2()    //1, f1函数里的this永久的绑定到了obj对象上, 无法更改

作为对象的方法内的this

  • this所在的函数作为对象的方法调用时, this指向调用该函数的对象
var obj = {
    a:1,
    "fn": function () {
        var a = 2
        return this.a
    }
}
obj.fn()    //1

obj.fn()并没有返回2, 而是返回1, 可见fn函数中的this指向了obj对象而不是fn函数, 那么this.a就是obj.a
obj.fn()可以看成这样:

obj.fn.call(obj) 
//等同于
obj.fn()

箭头函数内的this

  • 箭头函数内的this指向箭头函数创建时的封闭的词法上下文(the enclosing lexical context). 即, 箭头函数内部的this值为创建箭头函数时的this值. 换句话说, 箭头函数体内的this对象是定义箭头函数时时所在的对象.
function fn() {
    //假设this.form指向<form>元素
    this.form.addEventListener('submit', function() {
        console.log(this)   //这个this是什么?, 这个this指向外面的this.form, 即<form>元素
    }, false)
}

通过addEventListener添加的监听函数, 其内部this指向调用该处理函数的元素. 在上例中, this.form添加监听函数, 其处理函数内部的this就指向调用元素form表单
如何使处理函数内部的this也指向this.form中的this呢? 我们可以使用箭头函数:

function fn() {
    //假设this.form指向<form>元素
    this.form.addEventListener('submit', ()=>{
        console.log(this)   //这个this就是this.form中的this
    }, false)
}
  • 全局环境下, this指向的就是全局对象(不管严格模式下还是非严格模式下)
var fn = ()=>{return this}
fn()    //返回window对象

构造函数内的this

当一个函数使用new操作符时, 我们可以称这个函数为构造函数, 其内部的this指向正在构造的新对象.

  • 当构造函数没有return语句或者return的不是对象时, 构造函数会隐式的返回this对象
function fn() {
    this.a = 100   //没有return语句, 则会产生隐式的return this
}
var obj = new fn()  //产生新对象obj
console.log(obj.a)  //100
  • 当构造构造函数返回新对象时, this指向返回的新对象
function fn() {
    this.a = 100
    var o = {a: 1}
    return o    //这里返回对象o
}
var obj = new fn()  //产生新对象obj
console.log(obj.a)  //1, this指向了对象o

注意, 新对象不继承构造函数内部的属性. 新对象只继承this对象上的属性

function fn() {
    var x = 2
    this.a = 100
    this.b = 101
}
var obj = new fn()
console.log(obj.x)  //undefined
console.log(obj.a)  //100
console.log(obj.b)  //101

函数fn内的属性a并没有继承给obj对象, 而this上的a,b属性继承给了obj对象.

DOM事件处理函数中的this

我们常在DOM事件处理函数中使用this, 此时处理函数中的this指向调用这个函数的元素, 也是事件对象eventcurrentTarget对象, 即event.currentTarget

//假设有元素<button id="btn">点我</button>, 并绑定下面的监听事件
btn.addEventListener('click', function(e) {
    console.log(this)
    console.log(this === e.currentTarget)
}, false)
//当点击按钮时输出
<button id="btn">点我</button>
true

我们可以看到处理函数内部的this指向idbtn的元素

内联事件处理函数中的this

内联事件中的this有两种情况. 以onclick属性为例:

  • 一种是this指向onclick监听的DOM元素:
<button onclick="alert(this);">点我</button>
//this指向<button>元素
  • 另一种是this指向全局对象window:
<script>
  function fn() {
    return this
  }
</script>
<button onclick="alert(fn());">点我</button>
//this在函数内部, 指向window对象

总结

  • this的值取决与它的调用方式
  • 全局环境中的this指向window对象
  • 函数常规调用如fn()中的this在非严格模式下指向window, 严格模式下为undefined
  • this值为call, apply, bind中的第一个参数
  • 对象方法内的this指向调用该方法的对象
  • 箭头函数内的this指向创建箭头函数时的外部this
  • 构造函数内的this指向构造函数返回的新对象
  • DOM事件处理函数中的this指向调用处理函数的元素, 也是事件对象eventcurrentTarget属性即event.currentTarget.
  • 内联事件处理函数中的this指向调用处理函数的元素或者window

参考文章: this-JavaScript | MDN

猜你喜欢

转载自blog.csdn.net/helloyongwei/article/details/80382232