首先,需要明确一点,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对象