javascript中this指向问题

74 阅读3分钟

js中this指向问题一直是一个面试常问的问题,今天我就用一些案例,为大家详细解释this的指向。 案例1,普通函数直接调用,和通过new 关键字调用

/*普通函数中的this,谁调用它,它就代表谁*/
function F(name) {
  this.name = name;
  this.info = function () {
    console.log(this.name);
  };

  function f1() {
    // 这里的this和函数体的this不是同一个
    console.log(this.name);
  }

  f1();// 直接调用,调用者默认为window,不管F是直接调用还是用new调用,this指向window
  f1.call(this);// 调用者为this,函数F直接调用this指向window,通过new调用,指向实例
}

var name = "window";
// 通过new关键字调用,this指向新构建的对象
let a = new F("obj"); // window , obj
a.info();//obj,调用对象的info方法,调用者为a实例
a.info.call();//window,调用a实例的info方法,没有调用者默认为window,因此函数内的this指window
//当直接调用类函数时,函数中的this全部都指window
F("test");//test,test,相当于修改了window.num的值
console.log(window.num);//test

案例二,箭头函数中的this

//箭头函数没有自己this,箭头函数中的this指向的是创建该箭头函数时的环境变量。因此不可以用new去生成对象
//在顶层定义的箭头函数,函数体内的this指的是window。
//不可以通过apply,call,bind,去改变箭头函数中this的指向
let f = (num) => {
    console.log(this.num) // 在全局中定义的箭头函数,this为window
};
f(0);//undefined,因为this代指window,而window.num不存在
var num = 1;//相当于window.num=1;
f(2);//1,输出window.num
f.call({num: 3}, 4);//1,虽然调用者是一个对象,它的num是3,但是this指的是window,输出是window.num

let f1 = (num) => {
    this.num = num;
    console.log(this.num)
};
f1(0);//0,this依然值的是window,这里相当于给num变量重新赋值。
f1.call({num: 1}, 2);//2,call方法不能更改this指向,因此输出的还是window.num
try {
    let a = new f("tom");
} catch (e) {
    console.log(e);//f is not a constructor
}

案例三,定义在函数内部的箭头函数


function f(param) {
  this.param = param;
  // 常规函数,作为属性方法
  this.fun = function () {
    console.log(1, this.param);
  };
  // 箭头函数,作为属性方法
  this.func = () => {
    console.log(2, this.param);
  };

  // 常规函数
  function f1() {
    console.log(3, this.param)
  }

  // 箭头函数
  let f2 = () => {
    console.log(4, this.param)
  };
  f1(); // 常规函数直接调用
  f1.call(window);
  f2(); // 箭头函数直接调用
  f2.call(window);
}

// 在全局环境中调用函数,那么箭头函数中的this指向window。
f("tom"); // tom tom tom tom
window.fun();//tom
window.func();//tom
window.fun.call({param: "spike"});//spike 说明常规方法this指向的是传入对象
window.func.call({param: "spike"});//call不能更改箭头函数中的this。this指向window
console.log("end");

// 通过new去创建对象
// 3,tom 3,tom,说明在用new方法创建对象的过程中,f1()函数的this指向的是window。
// 4,jerry 4,jerry,说明在用new方法创建对象的过程中,f2()箭头函数中函数的this指向的是实例。
let a = new f("jerry");
a.fun(); //jerry
a.func();//jerry
a.fun.call({param: "lux"});//lux 说明常规方法this指向的是传入对象
a.func.call({param: "lux"})//jerry 说明箭头函数中的this是new对象的环境

案例4,对象字面量中的this

var param = "jerry";
let obj = {
    param: "tom",
    f1: function () {
        console.log(this.param)
    },
    f2: () => {
        console.log(this.param)
    }
};
obj.f1();// tom
obj.f2();// jerry,因为对象是在全局作用域创建的,this指向的便是window
obj.f2.bind({param: "spike"})();//jerry