this 和 构造函数有return

一、 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。