默认绑定
最常用的函数调用类型:独立函数调用,这条规则可以看作无法应用其他规则时的默认规则
function one() {
console.log(this.a)
}
var a = 1
one() //1 非严格模式下 如果是严格模式下会输出undefined
one在调用时没有任何的修饰函数,因此只能使用默认绑定,this指向全局变量作用域,this.a被解析成全局变量a
隐式绑定
示例代码:
function one() {
console.log(this.a)
}
var obj = {
a : 1,
one : one
}
obj.one() //1
如上例所示,在对象被调用时,调用位置存在上下文对象,one被当作引用属性添加到obj中,当one被调用时,加上了对obj的引用,即此时函数引用有上下文对象,隐式绑定规则会把函数调用中的this绑定到这个上下文对象上,因此此时的this.a等同于obj.a
Tips:对象属性引用链中只有上一层或者说最里面一层在调用位置中起作用,例子:
function one() {
console.log(this.a)
}
var obj = {
a : 1,
one : one
}
var obj1 = {
obj : obj,
a : 2
}
obj1.obj.one() //1
隐式丢失
隐式绑定最常见的问题就是被隐式绑定的函数会丢失绑定的对象,即它会使用默认绑定,将this绑定到全局对象上
function one() {
console.log(this.a)
}
var obj = {
a : 1,
one : one
}
var another = obj.one
var a = 2
another() //2
虽然another是obj.one的一个引用,但是实际上,它引用的是one函数本身,因此此时another()是一个不带任何修饰的函数调用,会应用默认绑定
显示绑定
显示绑定常见的绑定形式就是使用函数call()和apply()修改this的指向,它们的第一个参数就是一个对象,是给this准备的,即在后面时this的指向域,示例代码:
function one() {
console.log(this.a)
}
var obj = {
a : 1,
}
one.call(obj) //1
硬绑定
有时显示绑定不一定能解决我们碰到的问题,比如我们需要将this强制绑定到一个对象上,之后无论怎么调用都无法修改this指向,示例代码:
function one() {
console.log(this.a)
}
var obj = {
a : 1,
}
var a = 2
var another = function () {
one.call(obj)
}
another() //1
another.call(window) //1
硬绑定将one的this强制绑定在了obj上,无论之后如何调用函数another(),它总会手动在obj上调用one
bind方法绑定
示例代码:
function one() {
console.log(this.a)
}
var obj = {
a : 1,
}
var another = one.bind(obj)
another() //1
bind()会返回一个硬编码的新函数,它会把你指定的参数设置为this的上下文并调用原始函数
new绑定
使用new来调用函数时需要注意的点
Tips:
- 创建(或者说构造)一个全新的对象
- 这个对象会绑定到函数调用的this
- 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
示例代码:
function one(a) {
this.a = a
}
var another = new one(1)
console.log(another.a)
使用new来调用one()时,会构造一个新对象并把它绑定到one()调用中的this上
判断this绑定规则
- 函数是否在new中调用(new绑定)?如果是的话this绑定的是新创建的对象
- 函数是否通过call、apply(显示绑定)或者硬绑定调用?如果是的话,this绑定是指定的对象
- 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象
- 如果都不是,使用默认绑定,如果在严格模式下就绑定到undefined,否则绑定到全局对象
以上绑定规则优先级由高到低,感兴趣的可以自己去动手验证一下
以上内容是个人的一点总结,如果有错误或不严谨的地方,欢迎批评指正,如果喜欢,欢迎点赞收藏
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。