JavaScript中普通函数箭头函数容易混淆的this指向

[[toc]]

普通函数this指向什么?

普通函数的this指向哪里?

  • this指向调用它的对象
  • 函数定义无法确定,只有函数执行时才能确定

普通函数有哪些?

  • 没有调用者的函数
  • 对象内函数
  • 使用apply
// 没有调用者的函数: this(非严格)指向全局window
function test(){
    
    
  console.log('this=',this) // this=window
}
test()
// 对象内函数: 只有1层,this指向调用者对象
const school = {
    
      
  name: 'abc',
  course(){
    
    
    console.log('this=',this) // this= school
    console.log('name=',this.name) // name=abc
  }
}
school.course()
// 对象内函数: 有多层对象,this指向最近调用者对象
const outer = {
    
      
  name: 'outer',
  inner:{
    
    
    name: 'inner',
    fn(){
    
    
      console.log('this=',this) // this= inner
      console.log('name=',this.name) // name=inner
    }
  }
}
outer.inner.fn()
// 使用apply: 方法fun内部的this为apply参数1,如果参数1为null,则默认全局对象
const obj1 = {
    
    name: '对象1'}
function fn(a){
    
    
  console.log('a=',a) 
  console.log('this=',this) 
  console.log('name=',this.name) 
}
// TEST
fn.apply(obj1,['haha'])
// a= haha
// this=obj1
// name= 对象1
fn.apply(null,['haha'])
// a= haha
// this=window
// name= undefined

箭头函数的this指向什么?

箭头函数的this指向哪里?

  • this最终指向定义它的作用域的this,
  • 如果没有定义时所在作用域this,则向上查找父级作用域的this
  • 考虑: 在箭头函数之前考虑this即可;

箭头函数有哪些?

  • 全局箭头函数
  • 普通对象下的箭头函数
  • 普通函数下的箭头函数
  • 箭头函数下的箭头函数
  • 使用apply

确定箭头函数的this的办

  • 是在箭头函数定义之前打印this
console.log(this) // 此时的this就是箭头函数的this
const fun = () => {
    
     ... }
// 1. 全局箭头函数: this(非严格)指向全局window
const test = ()=>{
    
    
  console.log('this=',this) // this=window
}
test()
// 2.1 一层普通对象下的箭头函数: 相当于fn上层的this 
const outer = {
    
    
  fn: () =>{
    
    
    console.log('this=',this)
  }
}
outer.fn() // this=window
// 2.2 多层普通对象下的箭头函数: 相当于fn上层的this 
const outer = {
    
    
  inner:{
    
    
    fn: () =>{
    
    
      console.log('this=',this)
    }
  }
}
outer.inner.fn() // this=window
// 3.1 普通函数下的箭头函数: 取决于普通函数作用域,fn2中的this取决于fn1,fn1中的this所在作用域是outer
const outer = {
    
    
    fn1 () {
    
    
    const fn2 = () => {
    
    
        console.log('this=', this) // this=outer
    }
    return fn2()
    }
}
outer.fn1()
// 3.2 箭头函数下的箭头函数: 取决于上层箭头函数作用域, fn2中的this取决于fn1,fn1中的this所在作用域是window
const outer = {
    
    
  fn1: () => {
    
    
    const fn2 = () => {
    
    
      console.log('this=', this) // this=window
    }
    return fn2()
  }
}
outer.fn1()
// 4.1 使用apply: apply只会影响函数调用者,不会影响定义者,因此apply对箭头函数this无影响
const obj1 = {
    
    name: '对象1'}
const fn = (a) => {
    
    
  console.log('a=',a) 
  console.log('this=',this) 
  console.log('name=',this.name) 
}
// TEST
fn.apply(obj1,['haha'])
// a= haha
// this=window
// name= undefined
fn.apply(null,['haha'])
// a= haha
// this=window
// name= undefined
// 4.2 使用call: 和apply类似
// 定义name变量: 全局对象和普通对象
window.name = '111'
const obj = {
    
    name: '222'}
// 普通函数
function getNameCommon(){
    
    
  console.log(`name=${
      
      this.name}, this=`,this)
}
// 箭头函数
const getNameArrow = () =>{
    
    
  console.log(`name=${
      
      this.name}, this=`,this)
}

// TEST 
getNameCommon() // name=111, this=window
getNameArrow() // name=111, this=window
getNameCommon.call(obj) // name=222, this=obj
getNameArrow.call(obj) // name=111, this=window

构造函数this指向什么?

构造函数

  • 没有return语句, this指向实例变量
  • 有return && return是基本类型(如数字,字符串,null),return无效,this指向原本实例变量
  • 有return && return是对象,则return之前this指向实例变量,return之后this指向return的对象
// 没有返回: this指向对象实例
function device1(name){
    
    
  this.name=name 
  console.log('this=',this) // this=device1
}
// 返回基本类型: this指向对象实例
function device2(name){
    
    
  this.name=name 
  console.log('this=',this) // this=device2
  return 1
}
// 返回引用类型: return之前this指向对象实例,return之后this指向返回对象
const obj = {
    
    name:'对象1'}
function device3(name){
    
    
  this.name=name 
  console.log('this=',this) // this=device3
  return obj
}

// TEST
let d1 = new device1('111')
console.log('d1.name=',d1.name) // 111
let d2 = new device2('222')
console.log('d2.name=',d2.name) // 222
let d3 = new device3('333')
console.log('d3.name=',d3.name) // 对象1 不是333

猜你喜欢

转载自blog.csdn.net/qubes/article/details/134313539
今日推荐