「前端每日一问(42)」this 指向谁?

320 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

本题难度:⭐ ⭐

执行下面的代码, 打印出来的值是什么?

全部答对,this 就掌握了。

牢记阿林总结的知识点:

  • 全局上下文的 this 指向 window。

  • 函数上下文的 this 指向不是固定不变的,取决于函数处于什么位置、以什么方式调用,可以总结成如下图:

image.png

优先级是new 调用 > call、apply、bind 调用 > 对象上的函数调用 > 普通函数调用。

注意:

阿林写这篇文章的目的,不是为了让大家死记硬背,而是为了给出一些思路和实践,让大家更好地理解 this。

一个资深的前端工程师来回答类似这种打印某个值输出什么,也不敢保证一定答对,这很正常。

关键在于,资深前端工程师和入门前端工程师的知识积累和思考方式不同,一个资深的前端工程师,即使忘了 this 指向这个东西,稍微翻一下文档,再动手实践一下,很快就记回来了。

而入门前端工程师如果不懂 this 指向,只知道死记硬背,不去实践的话,很快就会忘记,下次再问还是不会。

第1题

function fn() {
  console.log(this) // ?
}

fn()

第2题

'use strict'

function fn() {
  console.log(this) // ?
}

fn()

第3题

const obj = {
  lastName: 'lin',
  fn() {
    console.log(this)           // ?
    console.log(this.lastName)  // ?
  }
}

obj.fn()

第4题

const obj = {
  lastName: 'lin',
  fn() {
    console.log(this)          // ?
    console.log(this.lastName) // ?
  }
}

const fn = obj.fn

fn()

第5题

const person = {
  lastName: 'lin',
  wife: {
    lastName: 'xxx',
    fn () {
      console.log(this)          // ?
      console.log(this.lastName) // ?
    }
  }
}

person.wife.fn()

第6题

const o1 = {
  text: 'o1',
  fn () {
    return this.text
  }
}

const o2 = {
  text: 'o2',
  fn () {
    return o1.fn()
  }
}

const o3 = {
  text: 'o3',
  fn () {
    var fn = o1.fn
    return fn()
  }
}

console.log(o1.fn())  // ?
console.log(o2.fn())  // ?
console.log(o3.fn())  // ?

第7题

const o1 = {
  text: 'o1',
  fn () {
    return this.text
  }
}

const o2 = {
  text: 'o2',
  fn: o1.fn
}

console.log(o1.fn()) // ?
console.log(o2.fn()) // ?

第8题

const foo = {
  name: 'lin',
  sayName() {
    console.log(this.name)
  }
}

const bar = {
  name: 'xxx'
}

foo.sayName.call(bar)   // ?
foo.sayName.apply(bar)  // ?
foo.sayName.bind(bar)() // ?

第9题

function Person1 (name) {
  this.name = name
}
function Person2 (name) {
  this.name = name
  return {}
}
function Person3 (name) {
  this.name = name
  return {
    name: 'xxx'
  }
}
function Person4 (name) {
  this.name = name
  return 1
}

const p1 = new Person1('lin')
const p2 = new Person2('lin')
const p3 = new Person3('lin')
const p4 = new Person4('lin')

console.log(p1.name) // ?
console.log(p2.name) // ?
console.log(p3.name) // ?
console.log(p4.name) // ?

第10题

var lastName = 'xxx'
const obj1 = {
  lastName: 'lin',
  fn() {
    setTimeout(function() {
      console.log(this.lastName) // ?
    })
  }
}

const obj2 = {
  lastName: 'lin',
  fn() {
    setTimeout(() => {
      console.log(this.lastName) // ?
    })
  }
}

obj1.fn() 
obj2.fn() 

第11题

var lastName = 'xxx'
const obj1 = {
  lastName: 'lin',
  fn() {
    return () => {
      console.log(this.lastName) // ?
    }
  }
}

const obj2 = {
  lastName: 'lin',
  fn() {
    return () => {
      return () => {
        console.log(this.lastName) // ?
      }
    }
  }
}

obj1.fn()()
obj2.fn()()()

第12题

function foo() {
  return a => {
    console.log(this.a)
  }
}

const obj1 = {
  a: 2
}

const obj2 = {
  a: 3
}
 
const bar = foo.call(obj1) // ?
bar.call(obj2)             // ?     

第 13 题

var a = 100
const foo = () => () => {
  console.log(this.a)
}

const obj1 = {
  a: 2
}

const obj2 = {
  a: 3
}

const bar = foo.call(obj1) // ?
bar.call(obj2)             // ?

第 14 题

let a = 100
const foo = () => () => {
  console.log(this.a)
}

const obj1 = {
  a: 2
}

const obj2 = {
  a: 3
}

const bar = foo.call(obj1) // ?
bar.call(obj2)             // ?

答案

// 第1题
window

// 第2题
undefined

// 第3题
{lastName: 'lin', fn: ƒ}
'lin'

// 第4题
window
undefined

// 第5题
{lastName: 'xxx', fn: ƒ}
'xxx'

// 第6题
'o1'
'o1'
undefined

// 第7题
'o1'
'o2'

// 第8题
'xxx'
'xxx'
'xxx'

// 第9题
'lin'
undefined
'xxx'
'lin'

// 第10题
'xxx'
'lin'

// 第11题
'lin'
'lin'

// 第12题 箭头函数的绑定无法被修改
2
bar.call(obj2) 啥也不输出

// 第13题 原理同12题
100
bar.call(obj2) 啥也不输出

// 第14题 let 声明的变量不会挂载到 window 上
undefined 
bar.call(obj2) 啥也不输出

结尾

阿林水平有限,文中如果有错误或表达不当的地方,非常欢迎在评论区指出,感谢~

如果我的文章对你有帮助,你的👍就是对我的最大支持^_^

你也可以关注《前端每日一问》这个专栏,防止失联哦~

我是阿林,输出洞见技术,再会!

上一篇:

「前端每日一问(41)」手写 bind 函数

下一篇:

「前端每日一问(43)」用过可选链操作符( ?.) 吗?