javaScript中的 this

总结

  • 什么是this?
  • this的四种匹配规则

什么是 this ?

首先 this 是函数内部的一个特殊的对象, 存在于函数内部

清空对 this 的误解, 主要的误解有两点 , 这两点是不对的

  • this 指向函数自身
  • this 指向当前函数的作用域

正确的说法是, this 是都某个对象的引用, this 只有在运行的时候才真正的指定了对某个对象的引用, 而不是在你编写函数的时候确定的, this 的指向问题 之取决于函数调用的方式 可以大致分为四种方式

this 四种方式查询

1.默认规则

默认规则下的 this 在浏览器中指向 window

当函数没有任何的修饰直接调用, 匹配不到其他规则的时候 就会使用默认规则

var a = 1
function fn(){
    abc()
}
function abc(){
    console.log(this.a)
}
fn() // 1

2.隐式绑定

当某个函数 是某个对象的方法, 或者 某个对象的某个属性存储的是 某个函数的引用 这个时候 this 指向的是这个对象, 这个时候使用的就是隐式绑定了

let obj = {
    a : 1,
    fn : function() {
        console.log(this.a)
    }
}
obj.fn() // 1

function fn() {
    console.log(this.a)
}
let obj = {
    a: 1,
    fn: fn
}
obj.fn() // 1

以上两种情况的 在 指向函数的时候 函数中的 this 都是使用的 隐式绑定 , console.log(this.a) 就是console.log(obj.a)

这是正常情况的隐式绑定规则, 但是隐式绑定中存在这一种隐式丢失情况, 这个时候使用的绑定规则默认规则

隐式丢失

先重新理解下隐式绑定, 当一个函数的引用被储存在对象的属性中(记住这个引用), 当我们调用的是这个 对象属性一开始对这个函数的引用的时候 才会发送隐式绑定, 如果是调用其他的对这个函数的引用, 这个时候就发生了丢失, this 使用 默认绑定

var a = 0
function fn() {
    console.log(this.a)
}
var obj1 = {
    a: 1,
    fn: fn
}
var obj2 = {
    a: 2,
    fn: obj1.fn
}
var fn = obj2.fn
obj2.fn() // 2
fn() // 0

这里面, obj2的属性fn存储着对一个函数的引用, 如果你调用这个对象的fn 属性的这个对函数的引用, 那么这个时候使用的是隐式绑定, 但是 fn = obj2.fn 这一步 fn 得到的是一个新的对这个函数的引用 , 这个引用和对象中fn属性存储的对函数的引用, 虽然都是指向同一个函数, 但是你可以把它理解成一个新的引用,这个时候调用这个新的引用就不是按照隐式绑定, 因为隐式绑定的规则是 调用的对象某个属性中存储的对某个函数的引用, 这个时候使用默认绑定 指向window

3.硬绑定

使用 函数的 call, apply , bind 方法, 在函数调用的时候强制将函数的this 指向某个对象

function fn() {
    console.log(this.a)
}
let obj = {
    a: 1
}
fn.call(obj) // 1

4.通过new绑定

关键字 new 在使用的过程中, 做了下面四件事

  • 创建一个对象
  • 给这个指向原型操作
  • 将函数的this指向这个对象
  • 返回这个对象
function fn() {
    this.a = 1  // 相当于 obj.a = 1
}
let obj = new fn()
console.log(obj.a) // 1

特殊的箭头函数

箭头函数是没有 this 的 他的 this 是继承来自外部的 this

并且 这个 this 不能被 call, bind , apply 修改

一道自测题

let obj1 = {
    a: 1,
    fn: function() {
        return () => console.log(this.a)
    }
}
let obj2 = {
    a: 2
}

obj1.fn()() // 1
obj1.fn().call(obj2) // 1
obj1.fn.call(obj2)() // 2

分析

obj1.fn()() , obj1.fn() 得到了一个新的函数 但是这个函数是 箭头函数, 这里面 的this继承的是 obj.fn() 调用时 函数 里的this 指向 obj1

obj1.fn().call(obj2) obj1.fn() 返回一个箭头函数 , this 继承 指向的是 obj1 , 通过 call() 方法调用, 但是 call 箭头函数的this 是继承来的 不会被修改 所以还是指向 obj1

obj1.fn.call(obj2)() obj1.fn.call(obj2) 首先call() 方法调用了 fn 方法, 并且将这个fn 方法的this 指向了 obj2, 返回了一个箭头函数, 继承 fn this , 这个 this 指向的是 obj2

posted @ 2019-12-25 13:53  达文西9527  阅读(298)  评论(0)    收藏  举报