this绑定及面试题

基础知识-你所要知道你this五种绑定方式:

默认绑定(非严格模式下this指向全局对象, 严格模式下this会绑定到undefined)
隐式绑定(当函数引用有上下文对象时, 如 obj.foo()的调用方式, foo内的this指向obj)
显示绑定(通过call()或者apply()方法直接指定this的绑定对象, 如foo.call(obj))
new绑定
箭头函数绑定(this的指向由外层作用域决定的)

下来各种面试题来喽,盘他

1.默认绑定

var a = 10;
function foo () {
  console.log(this.a)
}
foo();

这个是最基础的,不要着急,继续往下看

## 1.2严格模式下

"use strict";
var a = 10;
function foo () {
  console.log('this1', this)
  console.log(window.a)
  console.log(this.a)
}
console.log(window.foo)
console.log('this2', this)
foo();

执行结果:
f foo() {…}
‘this2’ Window{…}
‘this1’ undefined
10
Uncaught TypeError: Cannot read property ‘a’ of undefined

注意点

  1. 开启了严格模式,只是说使得函数内的this指向undefined,它并不会改变全局中this的指向。因此this1中打印的是undefined,而this2 还是window对象。

  2. 另外,它也不会阻止a被绑定到window对象上。

1.3let 和const

let a = 10
const b = 20

function foo () {
  console.log(this.a)
  console.log(this.b)
}
foo();
console.log(window.a)

执行结果
undefined
undefined
undefined
注意点:
如果把var改成了let 或者 const,变量是不会被绑定到window上的,所以此时会打印出三个undefined。

** 1.4函数内嵌套函数**

var a = 1
function foo () {
  var a = 2
  function inner () { 
    console.log(this.a)
  }
  inner()
}

foo()

结果是1还是2呢,自己去试试吧,印象会更深刻哦

2.隐式绑定

切记:this 永远指向最后调用它的那个对象。
谁最后调用的函数,函数内的this指向的就是谁(不考虑箭头函数)。

function foo () {
  console.log(this.a)
}
var obj = { a: 1, foo }
var a = 2
obj.foo()

结果为:1

1.2隐式丢包

function foo () {
  console.log(this.a)
};
var obj = { a: 1, foo };
var a = 2;
var foo2 = obj.foo;

obj.foo();
foo2();

执行结果
1
2
分析
obj.foo()中this的指向是为obj的(可以看第二部分隐式绑定),所以obj.foo()执行的时候,打印出来的是obj对象中的a,也就是1。
但是foo2它不也是obj.foo吗?我只不过是用了一个变量foo2来盛放了它而已。所以你是不是认为它打印的也是1呢?

1.3

function foo () {
  console.log(this.a)
};
var obj = { a: 1, foo };
var a = 2;
var foo2 = obj.foo;
var obj2 = { a: 3, foo2: obj.foo }

obj.foo();
foo2();
obj2.foo2();

执行结果
1
2
3
分析
obj.foo()中的this指向调用者obj
foo2()发生了隐式丢失,调用者是window,使得foo()中的this指向window
foo3()发生了隐式丢失,调用者是obj2,使得foo()中的this指向obj2

1.4

function foo () {
  console.log(this.a)
}
function doFoo (fn) {
  console.log(this)
  fn()
}
var obj = { a: 1, foo }
var a = 2
doFoo(obj.foo)

执行结果
Window{…}
2
分析
这里我们将obj.foo当成参数传递到doFoo函数中,在传递的过程中,obj.foo()函数内的this发生了改变,指向了window。

注意:
如果你把一个函数当成参数传递到另一个函数的时候,也会发生隐式丢失的问题,且与包裹着它的函数的this指向无关。在非严格模式下,会把该函数的this绑定到window上,严格模式下绑定到undefined。

3. 显示绑定

强行使用某些方法,改变函数内this的指向

  • 使用.call()或者.apply()的函数是会直接执行的
  • bind()是创建一个新的函数,需要手动调用才会执行
  • call()和.apply()用法基本类似,不过call接收若干个参数,而apply接收的是一个数组

1.1

function foo () {
  console.log(this.a)
}
var obj = { a: 1 }
var a = 2

foo()
foo.call(obj)
foo.apply(obj)
foo.bind(obj)

执行结果
2
1
1
分析:
第一个foo() 都很好理解,这不就是默认绑定吗?😁
而第二个和第三个foo都使用了call或apply来改变this的指向,并且是立即执行的。
第四个foo,仅仅是使用bind创建了一个新的函数,且这个新函数也没用别的变量接收并调用,因此并不会执行。

1.2

var obj1 = {
  a: 1
}
var obj2 = {
  a: 2,
  foo1: function () {
    console.log(this.a)
  },
  foo2: function () {
    setTimeout(function () {
      console.log(this)
      console.log(this.a)
    }, 0)
  }
}
var a = 3

obj2.foo1()
obj2.foo2()

执行结果
2
window
3

var obj1 = {
  a: 1
}
var obj2 = {
  a: 2,
  foo1: function () {
    console.log(this.a)
  },
  foo2: function () {
    setTimeout(function () {
      console.log(this)
      console.log(this.a)
    }.call(obj1), 0)
  }
}
var a = 3
obj2.foo1()
obj2.foo2()

执行结果
2
{ a: 1 }
1

1.3

function foo () {
  console.log(this.a)
}
var obj = { a: 1 }
var a = 2

foo()
foo.call(obj)
foo().call(obj)

执行结果
2
1
2
Uncaught TypeError: Cannot read property ‘call’ of undefined

分析
foo()会正常打印出window下的a,也就是2
foo.call(obj)由于显式绑定了this,所以会打印出obj下的a,也就是1
foo().call(obj)开始会执行foo()函数,打印出2,但是会对foo()函数的返回值执行.call(obj)操作,可是我们可以看到foo()函数的返回值是undefined,因此就会报错了

今天就到这里吧,重磅留在后面,让我好好整理一下哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值