this指向及改变this指向的方法

1,775 阅读3分钟

this是js中的关键字,始终指向一个对象,this是一个指针

1.this的显示绑定和隐式绑定

显示绑定:

函数没有明确的调用对象的时候,将对函数的this使用默认绑定:绑定到window全局对象(函数fire一直居住在window里面)

  • 1.1全局函数
function fire(){
    console.log(this = window) //# fire是全局方法,this指向window
}
fire()  //true
  • 1.2函数内嵌套函数
function fire(){
    function innerFire(){
        console.log(this) //# 未明确调用对象,this指向window
    }
    innerFire() //# 独立函数调用
}

fire()

示例

var a = 1
console.log(a) // 1 全局变量a
console.log(this.a) // this指向window

function fire(){
    var a = 2;
    console.log(a) // 2 函数fire作用域a
    console.log(this.a)  // this指向window
    function innerFire(){
        var a = 3;
        console.log(a) // 3 函数innerFire作用域a,从自身作用域找,未找到则往上找
        console.log(this.a) // this指向window
    }
    innerFire()
}

fire() 

1.3 对象的属性值的内部函数

var obj = {
    fire:function(){
      function innerFire(){
        console.log(this) //未明确调用对象,此时this指向window
      }
      innerFire()
    }
}

obj.fire()

示例

    var a = 1;
    console.log(this.a); //this指向window
    var obj = {
        a:2,
        fire:function(){
        var a = 3;
        console.log(this.a)  // obj.fire(),obj执行了函数fire,所以this指向obj
        function innerFire(){
            var a = 4;
            console.log(this.a) // 未明确调用对象,this指向window
        }
        innerFire()
        }
    }
  obj.fire()

隐式绑定:

1.1 当一个函数被一个对象包含的时候,this就被隐式绑定到这个对象上了,这时候可以通过this访问对象里的其他属性。
在隐式绑定下:函数只是暂时住在包含对象的旅馆里,过几天可能又要搬家了。

var obj = {
    a:'111',
    fire:function(){
      console.log(this.a) //111,this指向obj
    }
 }
  obj.fire()

或者这样写

var fire = function(){
    console.log(this.a)
}

var obj = {
    a:111,
    fire:fire
}

obj.fire()
  • 1.2 动态绑定:将函数赋值给全局变量(this从宾馆搬回家了)
var obj = {
    a:1,
    fire:function(){
      console.log(this.a)
    }
 }
  var a = 2 //全局的变量a
  obj.fire()  // 1, obj执行了函数fire,所以this指向obj,
  var fireInGlobal = obj.fire; //因为fireInGlobal是全局变量,this从宾馆搬回家了
  fireInGlobal() //this指向window,输出2
var a = 2;
  var obj = {
    a:3,
    fire:function(){
      console.log(this.a)
    }
 }
  obj.fire()  //3

  function otherFire(fn){  //# otherFire是全局函数,this指向window
    fn()
 }
  otherFire(obj.fire)  //2, 

2.this的指向问题

2.1 全局环境作用域:this在全局环境始终指向window

2.2 函数环境作用域:函数由谁调用,this就指向谁

2.2.1 非严格模式环境下
function fn(){
    console.log(this) //window
 }
  fn()
  console.log(fn === window.fn)  //true
  console.log(this === window)  //true
  console.log(fn === this.fn)  //true
2.2.2 严格模式环境下  
a 全局环境下,this指向window  
b 函数环境下,this指向undefined

2.3 对象中的方法函数调用:this指向该方法所属的对象

同隐式绑定

2.4 构造函数中this始终指向新对象

2.5 通过事件绑定的方法: this 指向 绑定事件的对象

<button id="btn">点我</button>

oBtn.onclick = function(){
    console.log(this) //btn
}

2.6 自执行函数(匿名函数): 指向全局变量window

2.7 箭头函数:

  • 要点:
    a. 箭头函数的this是在定义函数时绑定的, 不是在执行过程中绑定的
    b. 箭头函数中的this始终指向父级对象
    c. 所有 call() / apply() / bind() 方法对于箭头函数来说只是传入参数, 对它的 this 毫无影响。

3.更改this指向

1.call()

var person = {
    name:'zf',
    age:18
 }

function lzf(x,y){
    console.log(x,y)
    console.log(this)
    console.log(this.name)
}

  lzf(1,2); //this指向window---1,2---window---null
  lzf.call(person,1,2) //this指向person---1,2---person---zf
  

2.apply()用法同call(),只是apply的第二个参数是数组,数组里面是函数的参数

lzf.apply(person.[1,2])

3.bind(),有点不一样,他并不是改变this的指向,而是创建一个新的函数体。

var Person = {
    name: "zf",
    age: 19
}

function lzf(x, y) {
    console.log(x + "," + y);
    console.log(this);
    console.log(this.name);

}

lzf.bind(Person, 4, 5); //只是更改了this指向,没有输出
lzf.bind(Person, 4, 5)(); //this指向Person-- 4,5  Person{}对象  zf

4.存储this指向到变量中

var oDiv1 = document.getElementById("div1");
oDiv1.onclick = function () {
    var _this = this; //将this储存在变量中,而且不改变定时器的指向
    setTimeout(function () {
        console.log(_this); //注意这里是_this,而不是this-- <div id="div1">点击</div>
        console.log(this); //定时器的指向没有被改变--仍然是window
    }, 1000)
}