., 有.的话,点前面是谁,this就指向谁,如果没有点,指向window规则:非严格模式默认指向window,严格模式指向undefined。
最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。
function foo() {console.log(this.a)
}
var a = 2
foo() // 2
解析:foo() 是直接使用不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则。foo 是属于独立函数调用的,触发了默认绑定,从而指向全局window。
隐式绑定的 this,指向调用函数的上下文对象
规则:会把函数调用中的 this 绑定到这个上下文对象。
function foo() {console.log(this.a)
}
const obj = {a: 2,foo: foo
}
// 通过 obj 对象调用 foo 函数
obj.foo() // 2
规则:对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。
function foo() {console.log(this.a)
}
var obj2 = {a: 2,foo: foo
}
var obj1 = {a: 1,obj2: obj2
}
obj1.obj2.foo() // 2
function foo() {console.log(this.a)
}
var obj = {a: 2,foo: foo
}
var bar = obj.foo // 函数别名!
var a = 'global' // a 是全局对象的属性
bar() // "global"
虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是 foo 函数本身,因此此时的 bar() 其实是一个不带任何修饰的函数调用,因此应用了默认绑定。
function foo() {console.log(this.a)
}
function doFoo(fn) {// fn 其实引用的是 foofn() // <-- 调用位置!
}
var obj = {a: 2,foo: foo
}
var a = 'global'// a 是全局对象的属性
doFoo(obj.foo)// "global"
参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值,所以结果和上一 个例子一样。
直接指定 this 的绑定对象,因此我们称之为显式绑定
如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该怎么做呢? 可以使用函数的 call(..) 和 apply(..) 方法
JavaScript 提供的绝大多数函数以及你自 己创建的所有函数都可以使用 call(..) 和 apply(..) 方法。
function foo() {console.log(this.a)
}
var obj = {a: 2
}
foo.call(obj) // 2
硬绑定是指一个函数总是显示的绑定到一个对象上
由于硬绑定是一种非常常用的模式,所以 ES5 提供了内置的方法 Function.prototype.bind, 它的用法如下
function foo(num) {console.log(this.a, num)return this.a + num
}
var obj = {
a: 2
}
// 调用 bind() 方法,返回一个函数,那么这个新函数的 `this`,永远指向我们传入的`obj`