this

当一个函数被调用时,会创建一个活动记录(执行上下文)。这个记录会包括函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。 this 就是这个记录的一个属性,会在函数执行的过程中用到。

随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。

一、作为函数调用

函数直接调用时的this
console.log(this);  //  window

function fn(){
    console.log(this);
}

fn(); // 在函数被直接调用时this绑定到全局对象。在浏览器中,window 就是该全局对象

内部函数的this

函数嵌套产生的内部函数的this不是其父函数,仍然是全局变量

function fn(){
    function fn1(){
        console.log(this);
    }
    fn1();
}

fn(); //  window  

改写一下:

function fn(){
    console.log('这是fn')
    console.log(this);   //  window
    function fn1(){
        console.log('这是fn1')
        console.log(this);  //   window
      function   fn2() {
           console.log('这是fn2')
           console.log(this);  // 依旧是window
         }
       fn2 ()
    }
    fn1();
}

fn();  
setTimeout、setInterval 中的this
function fn(){
    console.log(this);   //  window
    setTimeout(function(){
        console.log(this);  // window
    }, 200);
}

fn()

二、 作为构造函数调用

作为构造函数调用时,this指向实例对象

function Cat(name){
    this.name = name;
}
Cat.prototype.sayName = function(){
    console.log(this.name);
};

var p1 = new Cat('Munchkin');
p1.sayName();  // Munchkin

三、作为对象方法调用

  • 隐式绑定, 直接调用 cat.fn()
var cat = {
    name: 'Munchkin',
    fn : function(){
        console.log(this);
    }
};
cat.fn(); // 指向调用函数的对象 cat 

对象属性引用链中只有上一层或者说最后一层在调用位置中起作用。

  • 常见陷阱 ( “隐式丢失”): 将cat.fn 赋值给其他对象再调用
var fn2 = cat.fn;

fn2(); //  window
  • 将对象方法作为参数传递给函数,然后调用函数
function foo(){
  console.log(this.a)
}
function doFoo(fn) {
  console.log(fn)
  fn(); // <-- 调用位置!
}
var obj = {
  a: 2,
  foo: foo
}
var a  = "oops, global";
doFoo(obj.foo); //  "oops, global"

参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值(与上个例子类似)。

四、 DOM对象绑定事件

在事件处理程序中this代表事件源DOM对象(低版本IE有bug,指向了window)


  
  
  

五、使用 call ,apply ,bind 改变this 指向(显式绑定)

Function.prototype.call

fn.call(context, param1, param2...)

Function.prototype.apply

fn.apply(context, paramArray)

Function.prototype.bind

bind,返回一个新函数,并且使函数内部的this为传入的第一个参数

var fn3 = obj1.fn.bind(obj1);
fn3();
三者比较

共同点

  • 都可以改变 this 指向,第一个参数都是希望设置的this对象

不同点

  • call 和 apply的不同之处在于call方法接收参数列表,而apply接收参数数组; - call 和 apply 都是直接调用函数,而bind 是返回一个改变了this 指向的新函数,供后面调用(不是直接调用)

七、 关于 this 的题目

var name = 'window'

var person1 = {
  name: 'person1',
  show1: function() {
    console.log(this.name)
  },
  show2: () => console.log(this.name),
  show3: function() {
    return function() {
      console.log(this.name)
    }
  },
  show4: function() {
    return () => console.log(this.name)
  }
}
var person2 = {
  name: 'person2'
}

以下各输出什么:

person1.show1() 
person1.show1.call(person2)

 person1.show2() 
 person1.show2.call(person2)

 person1.show3()()
 person1.show3().call(person2)
 person1.show3.call(person2)()

person1.show4()()
person1.show4().call(person2)
person1.show4.call(person2)()

参考:

  • 《你不知道的JS》 P82~ P101

你可能感兴趣的:(this)