一、 es5中 this
1.在普通函数中的this总是代表他的直接调用者,默认情况下指向windos
2.在严格模式下,没有直接调用者的函数中的this是undefined使用
3.call,apply,bind,this指向的是绑定的对象;
4.构造函数中的this
二、 es6 箭头函数中 this
箭头函数中的this指向是固定不变的,指向的是定义它的环境,最近的作用域。
1、点击事件绑定的this指向
<body>
<button class="draw" id="draw">Draw</button>
<div onclick="func(this)" name="book1">click div</div>
<script>
function func(_this) {
console.log(_this); // 当前点击的div
console.log(this); // window
}
var drawDom = document.getElementById('draw');
drawDom.addEventListener('click',function(){
console.log(this) // 当前div
})
drawDom.addEventListener('click',() => {
console.log(this) // window
})
</script>
</body>
2、嵌套函数
和变量不同,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。
1、如果嵌套函数作为方法调用,其this的值指向调用它的对象。
2、如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)。
很多人误以为调用嵌套函数时this会指向调用外层函数的上下文。如果你想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内部函数都在同一个作用域内。通常用self来保存this。
——《犀牛书》8.2 函数调用
举例说明
var name = "windName"
var data = {
name:' d a taNam e',
fn: function (){
var name = "fnName"
console.log(this .name ) //输出:dataName this指向data
var fn2 = () =>{
var name = "fn2Name"
console.log(this.name) //输出:dataName
}
var fn3 = function(){
var name = "fn3Name"
console.log(this.name) //输出:windName
}
fn2();
fn3(); // ** 嵌套的函数调用 this指向window(非严格模式)
}
}
data.fn(); // 作为方法调用
输出: dataName dataName windName
var a = {
foo: 1,
bar: () => console.log(this.foo)//这里是箭头函数指向 定义该箭头函数的作用域
}
a.bar() //undefined this指向的window
三、 当函数构造函数有return时候
1.return的是五种简单数据类型:String,Numbe r ,Boolean,Null,Undefined。
这种情况下,忽视return值,依然返回this对象。
2.return的是Object 引用类型。
这种情况下,不再返回this对象,而是返回return语句的返回值
// 正常情况
function A(){
this.age = 12;
}
var a = new A();
a.age // 12
//举例
function A(){
this.age = 12;
return {}
}
var a = new A();
a.age // undefined return返回的是引用类型。返回的是 {}
//举例
function A(){
this.age = 12;
return {age: 99}
}
var a = new A();
a.age //输出: 99 return返回的是引用类型。返回的是 {age: 99}
//举例
function A(){
this.age = 12;
return 13
}
var a = new A();
a.age // 输出:12 return 12 返回的数值类型,返回this的对象
四、题型
示例1
function f(){
console.log(this)
}
var arr = [f,2,4]
arr[0]() // 输出:[f,2,4]。 这里this指向的是arr
var fun = arr[0]
fun() // 输入的是 window
var obj = {
f: function(){
console.log('obj==>',this)
}
}
// obj['f']()和obj.f() 调用一样 输出 {f: f函数}
obj['f']()
obj.f()
示例2
function f(){
console.log('==>',this)
}
var funs = {
f: function(a,b,c){
function f(){console.log('f==>',this) }
a() // 输出:==>window。 这里调用参数a 相当于windows.f ---> funs.f(windows.f,'d',2)
f() //输出:f==>window 调用最近作用域的f()函数。为什么不能window.f()调用?
arguments[0]() // 输出:[f(),'d',2] 。就是arguments本身 跟上面的数组调用一个道理
}
}
funs.f(f,'d',2)
为什么不能window.f()??。因为这里的f是在函数内部创建的,作用域在函数内。f()这里是自执行,并没有直接对象调用,所以f函数内指向的window。
注:this指向window,不一定该函数指向window作用域上。this指向和函数作用域不是相互。
示例3
var obj={
say:function(){
return function(){
console.log(this);//window
}
}
}
obj.say()();
执行obj.say()的时候返回的是个函数,后面再去调用的这个返回函数,相当于这样执行
var refun = obj.say()
refun()
实例4 settimeout
var obj = {
age:10,
getage:function(){
console.log(this.age)
}
}
setTimeout(obj.getage,1000) // undefined
setTimeout(function(){
console.log(this) // window
obj.getage() // 10
},1000)
第一个setTimeout,执行obj.getage 之后,相当于setTimeout的回调是一个匿名函数,执行的时候,函数内部未设置this的指向。相当于是普通函数调用。所以this默认指向window,所以结果是undefined。