浅谈JavaScript中this的指向问题及面试题

·  阅读 1255

写在前面

this 作为JavaScript中的一个关键字,它的复杂度很高,主要原因是它所处不同场景的代表的指向是不一样的。这里先做一个结论,重要事情说三遍:

this的指向是由上下文环境动态决定的

this的指向是由上下文环境动态决定的

this的指向是由上下文环境动态决定的

this指向实例场景

关于this的指向的不确定性,主要体现在如下几个应用场景中:

  • 全局环境
  • 普通函数调用
  • call/apply/bind函数调用
  • 对象属性方法调用
  • 构造函数调用
  • 箭头函数

全局环境

在全局环境中无论是否是严格模式,this 均指向全局对象,例如浏览器端的 window

// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true

a = 37;
console.log(window.a); // 37

this.b = "MDN";
console.log(window.b)  // "MDN"
console.log(b)         // "MDN"
复制代码

普通函数调用

当普通的函数,直接调用的时候,一般来说分两种情况:

  • 严格模式绑定到 undefined
  • 非严格模式绑定到全局对象 window
function foo(){
  console.log(this);  
}
function bar(){
  "use strict"; 
  console.log(this);
}
foo() // window
bar() // undefined
复制代码

call/apply/bind函数调用

call/apply 这两个函数对象到方法能立即执行某个函数,并且讲函数中的this绑定到你提供到对象上去

bind 方法永久的绑定函数中的this到指定对象上,并返回一个新函数,将来这个函数无论怎么调用都可以

function foo(){
  console.log(this);  
}
function bar(){
  console.log(this);
}
foo.call({name:'小米'}); // {name: "小米"}

const bar1 = bar.bind({num:123})
bar1() // {num: 123}
复制代码

对象属性方法调用

作为对象属性方法调用,都指向前面调用函数都那个对象。当然有的时候会出现各种变种或者干扰的面试题

const student = {
  name: "tom",

  fn: function () {
    return this;
  },
};
console.log(student.fn() === student);
复制代码

构造函数调用或者类上下文

构造函数作为JavaScript创建对象的那只大母鸡(实际上类是构造函数的语法糖),通常程序界有个段子叫做new 一个对象,谁还敢说程序员(媛)没有对象的,这种方式调用this指向的是你new出来的那个对象实例本身:

function Person(name){
  console.log(this);
  this.name = name
}

const p = new Person('tom')
console.log(p);
复制代码

箭头函数中的this

箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

var obj = {
  name: "tom",
  foo() {
    setTimeout(() => {
      console.log(this);
    }, 1000);
  },
};

obj.foo() // obj

复制代码

面试题

常见面试题有: 1、手写bind函数

Function.prototype.mybind = function (ctx, ...args) {
  const fn = this;
  return function () {
    fn.apply(ctx, args);
  };
};

function foo(x, y) {
  console.log(this, x, y);
}

const foo1 = foo.mybind({ name: "zhangsan" }, 10, 20);
foo1();

复制代码

2、new 操作符调用构造函数,具体做了什么?

  • 创建一个新的对象;
  • 将构造函数的 this 指向这个新对象;
  • 为这个对象添加属性、方法等;
  • 最终返回新对象。
分类:
前端
标签:
分类:
前端
标签: