this 的值到底是什么

5 篇文章 0 订阅

函数调用面试题回顾

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 了

箭头函数

fn = () =>{}
this =>箭头函数名所在this 的 外面this

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

要注意立即执行函数和setTimeout函数

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,最后看箭头函数的外围

var name ='111'
obj ={
	name:'abc',
	fn:function(){
		setTimeout(()=>{
			console.log(this.name)
		},0)
		}
}
obj.fn()
//abc
var name ='111'
obj ={
	name:'abc',
	fn:function(){
		setTimeout(function(){
		//function 匿名函数,函数名所在的this就在()中,里面没有,因此指向window
			console.log(this.name)
		},0)
		}
}
obj.fn()
//111

一题详解

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 Fn()
this =》新的对象

如果函数是通过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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值