this绑定规则有5种
1、默认绑定
自然调用,指向window
var foo = 123;
function print(){
this.foo = 234;
console.log(this); // window
console.log(foo); // 234
}
print();
1、let/const
定义的变量存在暂时性死区,而且不会挂载到window
对象上,因此print
中是无法获取到a和b
的。
2、对象内执行
foo
虽然在obj
的bar
函数中,但foo
函数仍然是独立运行的,foo
中的this
依旧指向window
对象。
3、函数内执行
与2类似
4、自执行函数
this指向window
2、隐式绑定
函数的调用是在某个对象上触发的,即调用位置存在上下文对象,通俗点说就是**XXX.func()**这种调用模式。
此时func
的this
指向XXX
,但如果存在链式调用,例如XXX.YYY.ZZZ.func
,记住一个原则:this永远指向最后调用它的那个对象
var a = 1;
function foo() {
console.log(this.a);
}
// 对象简写,等同于 {a:2, foo: foo}
var obj = {a: 2, foo}
foo();
obj.foo();
3、隐式绑定丢失(丢失后会默认绑定)
1、使用另一个变量作为函数别名
a = 1
var obj = {
a: 2,
foo() {
console.log(this.a)
}
}
var foo = obj.foo;
obj.foo();
foo();
2
1
obj.foo
赋值给foo
,就是将foo
也指向了obj.foo
所指向的堆内存,此后再执行foo
,相当于直接执行的堆内存的函数,与obj
无关
只要fn前面什么都没有,肯定不是隐式绑定。
2、将函数作为参数传递时会被隐式赋值
function foo() {
console.log(this.a)
}
function doFoo(fn) {
console.log(this)
fn()
}
var obj = { a: 1, foo }
var a = 2
doFoo(obj.foo)
Window {…}
2
obj.foo
作为实参,在预编译时将其值赋值给形参fn
,是将obj.foo
指向的地址赋给了fn
,此后fn
执行不会与obj
产生任何关系。fn
为默认绑定。
3、回调函数使得隐士绑定失效,直接指向this
var name='zcxiaobao';
function introduce(){
console.log('Hello,My name is ', this.name);
}
const Tom = {
name: 'TOM',
introduce: function(){
setTimeout(function(){
console.log(this)
console.log('Hello, My name is ',this.name);
})
}
}
const Mary = {
name: 'Mary',
introduce
}
const Lisa = {
name: 'Lisa',
introduce
}
Tom.introduce();
setTimeout(Mary.introduce, 100);
setTimeout(function(){
Lisa.introduce();
},200);
Window {…}
Hello, My name is zcxiaobao
Hello,My name is zcxiaobao
Hello,My name is Lisa
Tom.introduce(执行
:console
位于setTimeout
的回调函数中,回调函数的this
指向window
Mary.introduce
直接作为setTimeout
的函数参数(类似题目题目3.3
),会发生隐式绑定丢失,this
为默认绑定Lisa.introduce
执行虽然位于setTimeout
的回调函数中,但保持xxx.fn
模式,this
为隐式绑定。
4、显式绑定
通过call()、apply()、bind()
等方法,强行改变this
指向。
call()和apply()
函数会立即执行bind()
函数会返回新函数,不会立即执行函数call()和apply()
的区别在于call
接受若干个参数,apply
接受数组。
5、new绑定
使用new
来构建函数,会执行如下四部操作:
- 创建一个空的简单
JavaScript
对象(即{}
); - 为步骤1新创建的对象添加属性
__proto__
,将该属性链接至构造函数的原型对象 ; - 将步骤1新创建的对象作为
this
的上下文 ; - 如果该函数没有返回对象,则返回
this
。
function User(name, age) {
this.name = name;
this.age = age;
}
var name = 'Tom';
var age = 18;
var zc = new User('zc', 24);
console.log(zc.name)
zc
6、箭头函数绑定
箭头函数没有自己的this
,它的this
指向外层作用域的this
,且指向函数定义时的this
而非执行时。
this指向外层作用域的this
: 箭头函数没有this
绑定,但它可以通过作用域链查到外层作用域的this
指向函数定义时的this而非执行时
:JavaScript
是静态作用域,就是函数定义之后,作用域就定死了,跟它执行时的地方无关。
name = 'tom'
const obj = {
name: 'zc',
intro: () => {
console.log('My name is ' + this.name)
}
}
obj.intro()
My name is tom