看完这篇文章,不信你搞不懂JS的this

135 阅读2分钟

首先,需要明确一点,this是代码在运行时被绑定的,不是在定义时绑定的。如函数的this,不是在代码编译阶段确定的,是在函数调用时确定的;

this的四种绑定规则: 默认绑定、隐式绑定、显式绑定、new绑定

默认绑定

即函数如果被独立调用,则this默认绑定为window;所谓独立调用,即不是用.调用,也不是用new,bind,call 等调用;
案例1:

function fun()  {
    return function bar()  {
      console.log(this)
    }
}
let f = fun()
f()

很明显,结果为window,因为执行f(),相当于bar()函数的独立调用

案例2:

function foo()  {
   console.log(this)
}
let per = {
    age: 12,
    sing: foo
}
let fun = per.sing
fun()

结果为window,理由同案例一

隐式绑定

通过object.fun调用函数,函数里的this被默认绑定为object对象
案例1:

function foo()  {
   console.log(this)
}
let per = {
    age: 12,
    sing: foo
}
per.sing()

结果为per对象,因为sing是通过per对象调用的
案例2

var per1 = {
  name: 'jack',
  f: function() {
    console.log(this)
  }
}
var per2 = {
  name: 'marry',
  fun: per1.f
}
per2.fun()

结果为per2对象

显式绑定

通过call,apply,bind来调用函数,强制改变函数的this,称为显式绑定。

function fun() {
    console.log(this)
}

通常这样调用函数

fun()

其实也可以这样调用
fun.call() 或者 fun.apply()
fun()相当于后两者的简写,如果要改变fun的this,只需要fun.call(per1)或者fun.apply(per1),则fun函数的this指向per1。

但是,如果fun函数有参数肿么办?

fun(n1,n2) {
    console.log(this, this.name)
    return n1 + n2
}

只需要fun.call(per1, 2 , 4)或者fun.apply(per1, [2,4])即可;此时,fun函数的this指向obj1。
可以看出,call和apply的区别仅仅是入参的区别,call传参是一个一个传的,apply则通过数组的形式传递的。

bind和call,apply的区别在于bind绑定this后会返回一个绑定this后的函数

let f = fun.bind(per1, 2, 4)  
console.log(f())  // 6

此时fun里输出的this是per1;

new绑定

function Fun(name, age) {
    this.name = name  
    this.age = age
} 
let f = new Fun('jack', 18)

通过new调用函数时,其实是实例化构造函数,构造函数内部相当于有这样一步操作: let this = {},当给this赋完值后,会将this 返回,即f是返回的this对象