有四种调用函数的方式,弄清楚这四种调用方式,this的指向问题就好解决了。
情况1 函数调用
函数调用的this指向window
function foo() {
console.log(this.a)
}
var a = 1
foo()//1
复杂一点的情况
这种也属于函数调用,this指向window
var a=20
var foo = {
a:15,
b:function(){
console.log(this.a);
}
}
var f1 = foo.b
f1()//20
情况2 方法调用
方法调用的this: 谁调用函数,谁就是this
var a=20
var foo = {
a:15,
b:function(){
console.log(this.a)
}
}
foo.b()//15
复杂一点的情况
say函数被当做foo.b()这种形式调用,函数内部的this指向调用者
var a=20
function say(){
console.log(this.a)
}
var foo = {
a:15,
b:say
}
foo.b()//15
情况3 构造函数
这种调用函数的方法,this指向构造函数的实例
function foo(name) {
this.name = name
}
let b = new foo('jack')//b中有属性name
复杂一点的情况
涉及到this可以访问什么?
function foo(){
var _say = foo.prototype.say
return new _say()
}
foo.prototype = {
constructor:foo,
name:'jack',
say:function(){
console.log(this.name)
}
}
foo()//undefined
从打印的情况看,foo访问不到name,这是为什么?
this可以访问实例say本身的属性,也可以访问say.prototype,并不可以访问foo.prototype,所以打印undefined
要想访问怎么办?修改say.prototype为foo.prototype
function foo(){
var _say = foo.prototype.say
return new _say()
}
foo.prototype = {
constructor:foo,
name:'jack',
say:function(){
console.log(this.name)
}
}
//添加这行代码,改变say的默认原型
foo.prototype.say.prototype = foo.prototype
foo()//jack
上下文调用(call,bind,apply)
对于上下文调用的认识
- 三者都能改变函数内部this的指向
- call和apply会执行函数,bind不会执行函数,而是返回新函数(返回的新函数只改变了this的指向)
- call传递参数列表,apply传递数组
- 如果不传递第一个参数,this默认是window
先看apply和call
call和apply打印结果一样
function f1(){
console.log(this);
}
f1.call([1,3,5])
f1.call({age:20,height:1000})
f1.call(1)
f1.call("abc")
f1.call(true);
f1.call(null)
f1.call(undefined);
f1.call()
console.log('=====')
f1.apply([1,3,5])
f1.apply({age:20,height:1000})
f1.apply(1)
f1.apply("abc")
f1.apply(true);
f1.apply(null)
f1.apply(undefined);
f1.apply()
-
总结:call、apply方法的第一个参数:
- 1、如果是一个对象类型,那么函数内部的this指向该对象
- 2、如果是undefined、null,那么函数内部的this指向window
- 3、如果是数字,this对应的Number构造函数的实例
- 4、如果是字符串,this:String构造函数的实例
- 5、如果是布尔值,this:Boolean构造函数的实例
再看bind
返回一个新函数,新函数的逻辑和之前一样,只是改变了this的指向
let name = 'window' function foo(){ console.log(this.name)//打印foo } let newFoo = foo.bind({'name':'foo'}) newFoo()其他情况
箭头函数
-
首先箭头函数其实是没有
this的,箭头函数中的this只取决包裹箭头函数的第一个普通函数的this
function a() { return () => { return () => { console.log(this) } }
} console.log(a()()()) //window
##### 其他复杂一点的情况
> 通过上面的方法就能判断了
```js
var foo = {
say:()=>{
setTimeout(()=>{
console.log(this)
},100)
},
sing:function(){
setTimeout(()=>{
console.log(this)
},100)
},
//es6写法
eat(){
setTimeout(()=>{
console.log(this)
},100)
}
}
foo.say()//window
foo.sing()//foo
foo.eat()//foo
总结
通过网上找的一张图能够找到this(侵删),非常方便