this绑定规则
首先我们需要知道是this是在运行时被绑定的,所以this的绑定和定义的位置没有关系(箭头函数除外),而是和调用的位置有关
this的绑定规则有以下四种
- 默认绑定
- 隐式绑定
- 显式绑定
- new绑定
下面就一起来看看这几种绑定方式吧
1、默认绑定
独立的函数调用我们可以理解为函数没有被绑定到某个对象上进行调用;
下面我们看下面的例子
function getName() {
console.log(this); // window
}
getName();
上面代码中的函数直接被调用,没有进行对象的绑定,这种独立的函数调用会使用默认绑定,一般情况下默认绑定的函数中this指向的是window
function t1() {
console.log(this); // window
t2();
}
function t2() {
console.log(this); // window
}
t1();
上面代码中实现的是一个函数调用另一个函数的链式调用,函数里面的this依旧指向的是全局对象window,因为函数真正调用的时候并没有绑定到某个对象上
function parent(func) {
func()
}
function child() {
console.log(this); // window
}
parent(child);
上面代码中实现的是将函数作为参数传入到另外一个函数中,执行后发现this依旧指向window,原因是因为child在调用的时候并没有绑定任何对象
2、隐式绑定
在函数的调用位置中是通过某个对象发起的函数调用
function getThis() {
console.log(this.name); // why (说明this指定的是obj对象)
}
var obj = {
name: "why",
getThis: getThis
}
obj.getThis();
上面代码中的getThis方法调用的时候是通过obj.getThis()调用的,所以在getThis调用时this会隐式绑定到obj对象中
function getThis() {
console.log(this.name); // obj1 (说明this指定的是obj1对象)
}
var obj1 = {
name: "obj1",
getThis: getThis
}
var obj2 = {
name: "obj2",
obj1: obj1
}
obj2.obj1.getThis();
上面代码中通过obj2引用了obj1对象,再通过obj1对象调用getThis函数,那么getThis调用的位置上其实还是通过obj1进行调用的,所以this的绑定依旧是obj1
function getThis() {
console.log(this); // window
}
var obj1 = {
name: "obj1",
getThis: getThis
}
// 讲obj1的getThis赋值给fun
var fun = obj1.getThis;
fun();
上面代码将obj1中的getThis方法赋值给fun,然后执行fun,最终this的指向是window, 原因是因为obj1只是将getThis方法赋值给了fun,最终调用的是fun()相当于默认绑定,当然也就没有形成隐式绑定
3、显示绑定
如果我们不希望某个对象中含有某个函数的引用,但是在函数调用的时候希望函数的内部this指向这个对象,这个时候我们是可以通过call,apply,bind进行this的绑定,这些方法都是可以强制绑定this的,具体这三个方法有什么相同和不同点,可以看我上一篇(bind call apply的区别)这里不多赘言了
上面这种方式,明确的绑定了this指向的对象,称之为 显示绑定。
function getThis() {
console.log(this);
}
getThis.call(window); // window
getThis.apply({name: "why"}); // {name: "why"}
let bindFun = getThis.bind({name: 'bind'}) // {name: 'bind'}
bindFun()
上面代码使用call、apply、bind将行数绑定到了其他对象中
4、new绑定
在JavaScript中的函数可以当做构造函数来使用,所以我们可以使用new来创建实例。
使用new的时候会执行一下四步
- 创建一个全新的对象
- 这个新对象会被执行Prototype连接
- 将函数调用的this绑定到这个新对象
- 如果函数没有返回其他对象,表达式会返回这个新对象
// 创建Person
function Person(name) {
console.log(this); // Person {}
this.name = name; // Person {name: "why"}
}
var p = new Person("why");
console.log(p);