this到底指向谁

59 阅读2分钟
// 1.全域环境中的this
/**
 * 严格模式下this指向的是undefinded,但在非严格模式下this指向的就是window对象
 */
function f1(){
   console.log(this); 
}
function f2(){
   "use strict"
   console.log(this);
}
f1(); // window对象
f2(); // undefinded

 //此时的this仍然指向window,fn1依然是在window的全局环境中执行的
 //此时的打印等同于
 //console.log(window);
 //console.log(window.bar);
const foo = {
   bar: 10,
   fn: function(){
      console.log(this);
      console.log(this.bar);
   }
}
var fn1 = foo.fn;
fn1(); 

foo.fn(); //此时的this指向的就是foo,所以打印输出的就是 {bar: 10, fn: ƒ} 10


//2.上下文中的this
const student = {
   name: "LUCAS",
   fn: function(){
      return this;
   }
}
console.log(student.fn() === student); // 此时应该返回true

const person = {
   name: "Lucas",
   brother: {
      name: "Mike",
      fn: function (){
         return this.name;
      }
   }
}
console.log(person.brother.fn()); //Mike 就近

const o1 = {
   text: "o1",
   fn: function (){
      return this.text;
   }
}

const o2 = {
   text: "o2",
   fn: function (){
      return o1.fn();
   }
}

const o3 = {
   text: "o3",
   fn: function (){
      let fn = o1.fn;
      return fn();
   }
}

console.log(o1.fn()); // o1
console.log(o2.fn()); // o1
console.log(o3.fn()); // undefined

//3 bind,call,apply改变this指向
// call和apply是直接进行相关函数执行的,但是bind不会执行函数,而是返回一个新的函数
const foo2 = {
   name: "lucas",
   logName: function (){
      console.log(this.name);
   }
}

const bar = {
   name: "mike"
}
foo2.logName.call(bar);


//4.构造函数和this
function Foo1(){
   this.user = "Lucas";
   const o = {};
   return o;
}

const instance1 = new Foo1();
console.log(instance1.user); // undefined

function Foo2(){
   this.user = "Lucas";
   return 1;
}
const instance2 = new Foo2();
console.log(instance2.user); // Lucas
// 如果构造函数中返回的是一个对象,那么this指向这个返回的对象
// 如果返回的不是一个对象,那么this指向实例

//5.箭头函数中的this
//箭头函数中,this的指向由外层作用域来决定
const foo5 = {
   fn: function (){
      setTimeout(() => {
         console.log(this);
      });
   }
}

console.log(foo5.fn()); // {fn: f}

//6.this的优先顺序
function foo6(a){
   console.log(this.a);
}

const obj1 = {
   a: 1,
   foo: foo6
}

const obj2 = {
   a: 2,
   foo: foo6
}
obj1.foo.call(obj2);  //2
obj2.foo.call(obj1);  //1



function foo7(a){
   this.a = a;
}
const obj3 = {};
let bar2 = foo7.bind(obj3); //foo7中的this指向obj3
bar2(2); // 此时ob3为{a: 2}
console.log(obj3.a) //2

let baz = new bar2(3); //new绑定修改了bind中的this指向
console.log(baz.a);//3

function foo8(){
   return a => {
      console.log(this.a);
   }
}
const obj4 = {
   a: 2
}
const obj5 = {
   a: 3
}
const bar3 = foo8.call(obj4); //foo8的this绑定到了obj4上,bar3的this也绑定到了obj4上
bar3.call(obj5); // 2 箭头函数的绑定无法被修改

var a = 1;
//let a = 1; 执行以下函数后,this指向window。但是let和const声明的变量不会挂载到window上,所以此时为undefined
const foo9 = () => a => {
   console.log(this.a);
}
const obj6 = {
   a: 2
}
const obj7 = {
   a: 3
}
const bar4 = foo9.call(obj6);
bar4.call(obj7); // 1