- 全局上下文 非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)。
- 1.默认绑定 独立调用
- 普通函数调用,此时 this 指向 window
- 被嵌套的函数独立调用时,this默认指向了window
- 自执行函数 this默认指向了window
- 闭包中this默认指向window
- 2.隐式绑定 方法调用
当函数当作方法来调用,this指向了直接对象 - 3,显示绑定 间接调用( call() apply() bind() )
call() apply() bind() 把对象绑定到this上,叫做显示绑定 - 4.new绑定 构造函数调用 new
1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
2.使用return关键字来返回对象时,实例化出来的对象是当前的返回对象
隐式丢失
隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window
-
1.函数别名
把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系 -
2.参数传递
把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window -
3.内置函数setTimeout()和setInterval()
第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似 -
4.间接调用
将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
(p.foo=obj.foo)()
严格模式下this的指向
1.严格模式下,独立调用的函数内部的this指向了undefined
2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数
全局上下文 非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)
console.log(this === window);//true
'use strict'
console.log(this === window);//true
this.name = '111';
console.log(this.name); // 111
1.默认绑定 独立调用
- 普通函数调用,此时 this 指向 window
- 被嵌套的函数独立调用时,this默认指向了window
- 自执行函数 this默认指向了window
- 闭包中this默认指向window
普通函数调用,此时 this 指向 window
//函数独立调用,函数内部的this也指向window
function fn(){
console.log(this);//window
}
fn();
被嵌套的函数独立调用时,this默认指向了window
//被嵌套的函数独立调用时,this默认指向了window
var a=0;
var obj={
a:2,
foo:function(){
var that=this;
function test(){
console.log(this.a);//0
console.log(that.a);//2
}
test();
}
}
obj.foo();
自执行函数 this默认指向了window
//IIFF 自执行函数 this默认指向了window
var a=10;
function fooo(){
(function test(){
console.log(this);//window
console.log(this.a);
})();
}
var obj={
a:2,
fooo:fooo
}
obj.fooo();//10
(function(){
console.log(this);//window
})()
闭包中this默认指向window
//闭包中this默认指向window
var a=0;
var obj={
a:12,
foo2:function(){
var _this=this;
return function(){
return _this.a;//12
return this.a;//0
}
}
}
var fn=obj.foo2();
console.log(fn());
2.隐式绑定 方法调用
当函数当作方法来调用,this指向了直接对象
//当函数当作方法来调用,this指向了直接对象(。前面的对象)
function foo(){
console.log(this.a);
}
var obj={
a:1,
foo:foo,
obj2:{
a:2,
foo:foo
}
}
//foo()函数的直接对象是obj,this的指向指向了直接对象
obj.foo();//1
//foo()函数的直接对象是obj2,this的指向指向了直接对象
obj.obj2.foo();//2
3,显示绑定 间接调用( call() apply() bind() )改变this指向
注意:call() apply() bind()的区别:
在JavaScript中,call和apply都是为了改变某个函数运行时的上下文而存在的,换句话说就是为了改变函数体内部的this指向
bind是返回对应函数,便于稍后使用;apply、call则是立即调用
对于apply、call而言,作用完全
call() apply() bind() 把对象绑定到this上,叫做显示绑定
//call() apply() bind() 把对象绑定到this上,叫做显示绑定
var a=0;
function foo(){
console.log(this.a);
}
var obj={
a:2
}
foo();
foo.call(obj);
foo.apply(obj);
var fn=foo.bind(obj);
fn();
硬绑定时显示绑定的一个变种,使得this不能再被改变
//硬绑定时显示绑定的一个变种,使得this不能再被改变
var a=0;
function foo(){
console.log(this.a);
}
var obj={
a:2
}
var bar=function(){
foo.call(obj);
}
bar();//2
setTimeout(bar,2000);//2
bar.call(window);//2 这里的this不再改变回window
数组的forEach(fn,对象) map() filter() some() every()
//数组的forEach(fn,对象) map() filter() some() every()
var id="window";
function fn(el){
console.log(el,this.id);
}
var obj={
id:"fn"
}
var arr=[1,2,3];
arr.forEach(fn);//window window window
arr.forEach(function(el,index){
console.log(el,index,this);
},obj);
/* 1 0 {id: "fn"}
2 1 {id: "fn"}
3 2 {id: "fn"}*/
4.new绑定 构造函数调用 new
1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
2.使用return关键字来返回对象时,实例化出来的对象是当前的返回对象
function fn(){
console.log(this);
return;
}
//1.如果是new关键字来执行函数,相当于构造函数来实例化对象,那么内部的this指向了当前实例化的对象
var fn=new fn();
console.log(fn);//fn fn
function fn2(){
//this还是指向了当前对象
console.log(this);
//使用return关键字来返回对象时,实例化出来的对象是当前的返回对象
return {
name:"qqq"
}
}
var fn2=new fn2();//fn2()
console.log(fn2);//{name: "qqq"}
严格模式下this的指向
1.严格模式下,独立调用的函数内部的this指向了undefined
2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数
//1.严格模式下,独立调用的函数内部的this指向了undefined
function fn(){
'use strict'
console.log(this);
}
fn();//undefined
//2.严格模式下,函数apply()和call()内部的this始终是他们的第一个参数
var color="red";
function showColor(){
'use strict';
console.log(this);
console.log(this.color);
}
showColor.call(null);//null
隐式丢失
隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window
-
1.函数别名
把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系 -
2.参数传递
把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window
-3. **内置函数setTimeout()和setInterval()**第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似
- 4.间接调用
将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
(p.foo=obj.foo)()
//隐式丢失就是指被隐式绑定的函数丢失了绑定对象,从而默认绑定到window
//这种情况比较容易出错却又非常常见
//1.隐式丢失 函数别名
var a=0;
function foo(){
console.log(this.a);
}
var obj={
a:1,
foo:foo
}
var bar=obj.foo();
bar();
//把obj.foo赋值给了别名bar,造成隐式丢失的情况,因为只是把obj.foo()赋值了bar变量,而bar与obj对象毫无关系
//上面的函数相当于
var a=0;
var bar=function foo(){
console.log(this.a);
}
bar();
把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window
//2.参数传递
var a=0;
function foo(){
console.log(this.a);
}
function bar(fn){
fn()
}
var obj={
a:1,
foo:foo
}
bar(obj.foo)
//把obj.foo当作参数传递到bar函数中,有隐式的函数赋值fn=obj.foo,
//只是把foo函数赋值给了fn,而fn与obj对象毫无关系,所以当前foo函数内部的this指向了window
//上面的函数相当于
var a=0;
function foo(){
console.log(this.a);
}
function bar(fn){
fn()
}
bar(function foo(){
//内部的this指向了window
console.log(this.a);
})
内置函数setTimeout()和setInterval()第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似
//3.内置函数setTimeout()和setInterval()第一个参数的回调函数中的this,默认指向了window,跟第二种情况类似
var a=10;
function foo(){
console.log(this.a);
}
var obj={
a:1,
foo:foo
}
setTimeout(obj.foo,1000);
将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
(p.foo=obj.foo)()
//4.间接调用
function foo(){
console.log(this.a);
}
var a=2;
var obj={
a:3,
foo:foo
}
var p={a:4};
// 隐式绑定,函数当作对象中的方法来使用,内部的this指向了该对象
obj.foo();//3
//将obj.foo函数对象赋值给了p.foo函数,然后立即执行。相当于仅仅是foo()函数的 立即调用 ,内部的this,默认指向了window
(p.foo=obj.foo)();//2
//将obj.foo赋值给了p.foo函数,之后p.foo()函数再执行,其实是属于p对象的方法的指向,this指向了当前的p对象
p.foo=obj.foo
p.foo();//4
//5.其他情况,指向了window的特殊情况
var a=0;
var obj={
a:1,
foo:foo
}
function foo(){
console.log(this.a);
}
(obj.foo=obj.foo)();//0
(false||obj.foo)();//0
(1,obj.foo)()//0