- 函数在调用时,JavaScript会默认给this绑定一个值;
- this的绑定和定义的位置(编写的位置没有关系);
- this的绑定和调用方法以及调用的位置有关系;
- this是在运行时被绑定的
1.默认绑定
独立函数调用的情况下,this指向window,例如
function foo() {
console.log(this);
}
foo() //window
哪怕是多层调用,只要是使用默认调用的方法,this的指向都会是window对象
function test1() {
console.log(this);//window
test2()
}
function test2() {
console.log(this);//window
test3()
}
function test3() {
console.log(this);//window
}
test1()
下面这个案例感觉上是由obj对象调起的
function foo(func) {
func()
}
var obj = {
name: "sss",
bar:function() {
console.log(this)
}
}
foo(obj.bar)
事实上只是拿到了obj对象中的bar函数,依旧是独立调用
严格模式,独立函数指向的是undefined
2.隐式绑定
比较常见的调用方式是通过某个对象进行调用的。它的调用位置,是通过某个对象发起的函数调用。
function foo() {
console.log(this)
}
var obj = {
name: "sss",
foo:foo
}
obj.foo()
通过obj对象调用了foo函数,该this指向的是调用该函数的obj对象。
在多层嵌套的调用时,会是什么情况呢?
function foo() {
console.log(this)
}
var obj1 = {
name: "sss",
foo: foo
}
var obj2 = {
name: "aaa",
obj1: obj1
}
obj2.obj1.foo()
指向的是obj1对象,也就是说不管多少层调用,this都指向调用的那个对象。
3.new绑定
JavaScript中的函数可以当作一个类的构造函数来使用,也就是使用new关键字。
使用new关键字来调用函数时,会执行如下的操作
- 创建一个全新的对象;
- 这个新对象会被执行prototype连接;
- 这个新对象会绑定到函数调用的this上(this的绑定在这个步骤完成);
- 如果函数没有返回其他对象,表达式会返回这个新对象。
function person(name) {
console.log(this);
this.name = name
}
var p = new person("aaa")
console.log(p)
4.显式绑定
在隐式绑定中,必须在调用的对象内部有一个对函数的引用,如果没有这样的引用,在进行调用的时候,会报找不到该函数的错误。
如果我们不希望在对象内部包含这个函数的引用,同时又希望在这个对象上进行强制调用,可以使用call、apply、bind方法
JavaScript所有的函数都可以使用call和apply方法
4.1.apply
func.apply(thisArg, [argsArray])
第一个参数要求传入一个对象,调用这个函数的时候,会将this绑定到这个传入的对象上
function foo(name, age, height) {
console.log(this)
console.log("打印参数:",name, age, height);
console.log(this.name)
}
var obj = {
name: "zzz"
}
foo.apply(obj, ["aaa", 30 ,1.98])
apply方法传入参数的方法是写在数组中
4.2.call
func.call(thisArg, arg1, arg2, ...)
第一个参数传入一个对象,后面的参数传入实参
function foo(name, age, height) {
console.log(this)
console.log("打印参数:",name, age, height);
console.log(this.name)
}
var obj = {
name: "zzz"
}
foo.call(obj, "aaa", 30 ,1.98)
4.3.apply和call的第一个参数
通过call或者apply绑定this对象,this就会明确指向指定的对象。
而且不止可以指向明确的对象,还可以指向window、Number、String对象
function foo(name, age, height) {
console.log(this)
}
var obj = {
name: "zzz"
}
foo.call(obj, "aaa", 30 ,1.98)
foo.call(window)
foo.call(123)
foo.call("string")
4.4.bind
如果我们希望一个函数总是显式绑定到一个对象上,可以使用bind方法
function foo(name, age, height) {
console.log(this)
}
obj = {
name: "zzz"
}
var bar = foo.bind(obj, "aaa", 30 ,1.98)
bar()
5.规则优先级
- 默认规则的优先级最低
- 显式绑定优先级高于隐式绑定
- new绑定优先级高于隐式绑定
- new绑定优先级高于bind
new绑定 > bind绑定 > call/apply绑定 > 隐式绑定 > 默认绑定
6.this规则之外
忽略显式绑定
如果在显式绑定中,我们传入一个null或者undefined,那么这个显式绑定会被忽略,使用默认规则
function foo() {
console.log(this)
}
var obj = {
name: "zzz"
}
foo.call(obj) // obj对象
foo.call(null) //window
foo.call(undefined) //window
var bar = foo.bind(null)
bar() // window
间接函数引用
创建一个函数的间接引用,这种情况使用默认绑定规则
function foo() {
console.log(this)
}
var obj1 = {
name: "obj1",
foo: foo
}
var obj2 = {
name: "obj2"
}
obj1.foo() //obj1对象
(obj2.foo = obj1.foo)() //window
7.箭头函数的this
箭头函数不使用this的四种标准规则(也就是不绑定this),而是根据外层作用域来决定this