欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

this 的值到底是什么

程序员文章站 2022-06-17 18:18:05
...

函数调用面试题回顾

var obj = {
	foo:function(){
		console.log(this)
	}
}
var bar =obj.foo
obj.foo()  //打印出的this是obj
bar()  //打印出的this是window
window.n = 'window name'
let obj = {
    n: 'obj name',
    sayN(){
        console.log(this.n)
    }
}
let fn = obj.sayN
fn()  // window name
window.n = 'window name'
let obj = {
    n: 'obj name',
    sayN: () => {
        console.log(this.n)
    }
}

obj.sayN() // window name

有没有主体,有:obj;注意看是否是箭头函数,此时sayN的this指向的是obj,因此箭头函数this指向外围:window

function fo (i) {
  console.log('fo', i)
  console.log(this === window) // true
  this.count++
}

fo.count = 0

for (var i = 0; i < 5; i++) {
  fo(i)
}
console.log(fo.count, count) // 0, NaN

函数执行fo(),前面没有主体,因此this指向window,window.count为NaN,因为window.count没有初始化

老师的理解

func(p1, p2)
obj.child.method(p1, p2)

第一道第一种
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)

第二道
func(p1, p2) 等价于
func.call(undefined, p1, p2)

如果你传的 context 是 null 或 undefined,那么 window 对象就是默认的 context,因此上面的打印结果是 window

如果你希望这里的 this 不是 window,很简单:
func.call(obj) // 那么里面的 this 就是 obj 对象了

我的理解

两种形式,首先看函数名前面有没有主体,接着看是否是箭头函数
func(p1, p2)
obj.child.method(p1, p2)

[ ] 语法

function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?

相当于arr.0() —> 无非两种,看函数名前是否有主体
与转换代码里的 obj.child.method(p1, p2) 对应上
所以里面的 this 就是 arr 了

箭头函数

箭头函数里并没有 this,如果你在箭头函数里看到 this,你直接把它当作箭头函数外面的 this 即可

window.n = 'window name'
let obj = {
    n: 'obj name',
    sayN: () => {
        console.log(this.n)
    }
}

obj.sayN() // window name

此处sayN不是箭头函数则this指向obj,现在指向obj的外部,因此是window

var name = 'global'

var obj = {
  name: 'obj',
  test: function () {
    // 这里的this指向obj
    (() => {
      // 注意这里的是箭头函数 
      var name = '2'
      console.log(this.name)
    })()
  }
}

obj.test() // obj

首先看函数名前面有没有主体:obj,接着看是否是箭头函数,可以确定的是test{}里的this是obj,最后看箭头函数的外围

一题详解

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

var obj1 = {
  name: 'obj1'
}

var obj2 = {
  name: 'obj2'
}

var temp = foo.call(obj1)
temp.call(obj2) // obj1

相当于

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

var obj1 = {
  name: 'obj1'
}

var obj2 = {
  name: 'obj2'
}

foo.call(obj1) //obj1

foo()执行,this指向obj1,通过立即执行函数获得外围this,因此打印obj1。上图输入temp.call(obj2),也就是temp(),在箭头函数那this指向obj2,在箭头函数里this指向obj2的外围

foo = ()=>{
    console.log(this.name)
}  
var obj1 = {
  name: 'obj1'
}
var obj2 = {
  name: 'obj2'
}
 foo.call(obj1) //global
function foo(){
    console.log(this.name)
}
var obj1 = {
  name: 'obj1'
}
var obj2 = {
  name: 'obj2'
}
 foo.call(obj1)  //obj1

new X

如果函数是通过new调用(new绑定), 那么this指向新创建的对象

  1. 创建一个全新的对象
  2. 该新对象关联到大X原型, 把该对象绑定到大X this
  3. 执行函数中代码
  4. 如果没有其他返回, 默认返回该新对象(自动return this)
function Person () {
  this.name = '2'
}
console.log(new Person().name) // 2
class A{
    constructor(){
        this.name = 'A'
    }
    sayName(){
        console.log(this.name)
    }
}
class B extends A{
    constructor(){
        super()
        this.name = 'B'
    }
}

let obj = new B()
console.log(obj.sayName()) //B

函数前面有主体obj,obj this指向B

function test (thing) {
  this.thing = thing
}
var obj1 = {
  test: test
}
var obj2 = {}
// 隐式绑定
obj1.test(2)
console.log(obj1.thing) // 2
// 显示绑定
obj1.test.call(obj2, 3)
console.log(obj2.thing) // 3

// 可见new绑定优先级高于隐式绑定, 如果不是的化 test.thing=2
var test = new obj1.test(4)
console.log(obj1.thing) // 2
console.log(test.thing) // 4

文章参考链接
一文搞懂this关键字
https://zhuanlan.zhihu.com/p/84944648
this 的值到底是什么?一次说清楚
https://zhuanlan.zhihu.com/p/23804247
你怎么还没搞懂 this?
https://zhuanlan.zhihu.com/p/25991271