this指向 以及call apply bind

this

首先,必须记住一点。this的指向是在函数执行的时候才能确定,this的最终指向的是最终调用它的对象

先来个例子1;
 function test(){
  let  name = 'kobe'
  console.log(this.name)   //undefined
  console.log(this)  //window
}
test()

上述代码就可以证明this指向的是调用它的对象 上述代码在全局下 this指向的是window

例子1-1
 function test(){
  let  name = 'kobe'
  console.log(this.name)   //undefined
  console.log(this)  //window
}
window.test()
例子1-1

证明了全局下的函数执行this指向window

例子2
let obj = {
  name:'kobe',
  fn(){  console.log(this.name)}  
}
obj.fn()  //kobe

例子2中的this指向对象obj 因为调用这个函数是由obj这个函数调用的。这里指向开头说的结论,就是开头黑黑的那句话。

但是下面的例子会推翻该结论

例子3(看标注为第二份的代码) (例子三这里插个题外话本来是用第一份做示例的)

第一份

let obj = {
    name:"kobe",
    fn(){
        console.log(this.name); 
    }
}
window.obj.fn(); //发现fn显示未定义  其实是let声明的对象不挂载在window上

第二份

var obj = {
    name:"kobe",
    fn(){
        console.log(this.name); 
    }
}
window.obj.fn(); //kobe
例子3推翻了前面的结论 明明是window(window上没有name属性)调用了该函数 怎么会打印kobe。其实this指向的是 在函数调用的时候 层级离它最近的对象
例子3-1
let obj = {
    name:"kobe",
   obj1:{
     name:'curry',
       fn(){
        console.log(this.name); 
    }
   }
}
obj.obj1.fn()   // curry  这里打印的是obj1的name
let obj = {
    name:"kobe",
   obj1:{
    
       fn(){
        console.log(this.name); 
    }
   }
}
obj.obj1.fn()   // undefined  这里打印的是obj1的name
总结 分为三种情况

1、如果一个函数中有this,但是它没有被上一级的对象所调用那么this指向的就是window(在严格模式中 为undefined)
2、如果一个函数中有this,这个函数有被上一级的对象调用,那么this指向的就是上一级的对象
3、如果一个函数中有this,这个函数是在层级较深的对象中定义的方法,this指向的也只是调用它的时候的上一级的对象。

例子4
let obj = {
    name:'kobe',
  obj1:{
       name:'curry',
       fn(){
        console.log(this.name)  
        console.log(this)  
      }
}
}
 let fn = obj.obj1.fn
 fn()   // 会打印undefined 和 window

由于例子4是将obj1内的函数取出放在 fn中 所以在当直接执行的时候是在全局下执行的 这里的this指向的是window

构造函数中的this

例子1
function Fn(){  
this.name = "kobe"
}
let a = new Fn();
console.log(a.name)  //kobe

在new 的过程中相当于 复制了一份Fn到对象a里面,此时仅仅只是创建,没有执行 用a.name的时候代表条用这个函数的对象是a,this就指向a,由于复制了一份Fn到对象a中所有 对象a中有name

例子2(在构造函数中当遇到return的时候)
 function fn()  
{  
    this.name = 'kobe';  
    return {name: 'curry'};  
}
let a = new fn();  
console.log(a.name); //curry
 function fn()  
{  
    this.name = 'kobe';  
    return function(){};  
}
let a = new fn();  
console.log(a.name); //undefined
 function fn()  
{  
    this.name = 'kobe';  
    return 1;  
}
let a = new fn();  
console.log(a.name); //kobe
 function fn()  
{  
    this.name = 'kobe';  
    return undefined;  
}
let a = new fn();  
console.log(a.name); //kobe

上述4个例子说明 在构造函数中 this指向的就是new 的时候构造函数返回的对象(除了null之外虽然null也 是对象 比较特殊) 如果不是对象那么this还是指向函数的实例

接下来就可以折腾call,apply,bind了

在需要指定this指向的情况下,会出现这写问题
问题场景我需要条用b调用a中的方法并且用到a中的属性

let a ={  
     name:'kobe',
     fn(){ 
       console.log(this.name)}
      }
let b =a.fn 
 b()   //undefined

显然这样是不行的可以用到call

let a ={  
     name:'kobe',
     fn(){ 
       console.log(this.name)}
      }
let b =a.fn 
 b.call(a)   //kobe

通过call方法将this指向从window改为a对象

1、call方法之后还可以添加方法的对应参数

let a ={  
     name:'kobe',
     fn(a,b){ 
       
       console.log(`${this.name}:${a+b}`)}
      }
let b =a.fn 
 b.call(a,1,2)   // kobe  3

2、apply方法和call类似就是传递参数的时候是用数组传的

let a ={  
     name:'kobe',
     fn(a,b){ 
       
       console.log(`${this.name}:${a+b}`)}
      }
let b =a.fn 
 b.apply(a,[1,2])   // kobe  3

如果call和apply的第一个参数写的是null,那么this指向的是window对象

let  a ={
  name:"kobe",
  fn() {
    console.log(this.name) 
    console.log(this)
   }  
}
 let b = a.fn
b.apply(null)  // undefined window 

3、bind()

bind()方法和call、apply方法有些不同,但是都可以改变this的指向

 let  a ={
  name:"kobe",
  fn(a,b) {
    console.log(`${a+b}`)
    console.log(this.name) 
    console.log(this)
   }  
}
 let b = a.fn
b.bind(null)  
b.bind(null)(1,2) //3 undefiend window 

区别在于bind改变指向后不会立即执行 而是一个函数 还需要调用一下才行
所以用bind改变this的指向 函数不用立即执行 而是想在哪用在哪用 传递参数在调用的时候的括号里传

你可能感兴趣的:(this指向 以及call apply bind)