this的指向

为什么需要this?

image.png
image.png
没有this的话,上图的obj改名了,里面的所有都要跟着改,非常不方便。

而用this,指向的就是这个对象自己,不管你外面怎么改名字。

this指向什么?

浏览器:window
image.png
image.png
nodejs:{}
image.png
nodejs环境,是把单个文件当做模块执行,然后调用函数.apply({}) 的方式,把整个文件绑定给空对象

image.png
这里的this,会根据规则动态绑定,并非像函数执行上下文(FEC)、作用域链那样编译的时候就确定,如下例子:

image.pngimage.png

绑定规则

1、默认绑定

独立的函数调用,我们可以理解成函数没有被绑定到某个对象上进行调用(在全局的环境下调用)。

浏览器的this:window
nodejs的this:{ } 空对象
image.png

2、隐式绑定

是通过某个对象进行调用的,

image.png

3、显式绑定

通过call 、 apply 、bind 方法手动绑定某个对象

call 、 apply,第一个参数就是你指定的this,区别在于后面传参的方式而已
image.png

bind 是创建一个新的函数并重新指定this,然后赋值给其他标识符,调用这个标识符就默认是这个绑定的this。
后面传参数和call一样的,通过逗号
image.png
image.png

4、new 绑定

JavaScript中的函数可以当做一个类的构造函数来使用,也就是使用new关键字

使用new关键字来调用函数是,每次会执行如下的操作:

  1. function Person(){}
  2. new Person()

1、创建一个全新的对象 { };

  1. function Person(){
  2. var obj = {}
  3. }

2、这个新对象会绑定到函数调用的this上

  1. function Person(){
  2. var obj = {}
  3. this = obj // 这里只是演示这个意思,不能这样写
  4. }

3、如果函数没有返回其他对象,表达式会返回这个新对象

  1. function Person(){
  2. var obj = {}
  3. this = obj // 这里只是演示这个意思,不能这样写
  4. return this
  5. }
  6. var p = new Person()
  7. // p = obj 相当于

image.png

规则优先级

1、new > 隐式 > 默认
image.png({ })

2、显式 > 隐式 > 默认
image.png(’abc’)
image.png(’aaa’)

3、new 和 显式绑定
image.png
image.png({ })

内置函数的绑定

image.png
forEach等某些函数,默认是window,可以额外传入this参数,后面的执行都会绑定这个this参数
image.png

规则之外

1、忽略显示绑定

传入一个null或者undefined,那么这个显示绑定会被忽略,使用默认规则
image.png

2、间接函数引用

创建一个函数的 间接引用,这种情况使用默认绑定规则。如下的最后一行代码(可能一辈子都用不上,主要是面试)
image.png

3、严格模式

  1. // 在严格模式下, 自执行函数(默认绑定)会指向undefined
  2. // 之前编写的代码中, 自执行函数我们是没有使用过this直接去引用window
  3. function foo() {
  4. console.log(this)
  5. }
  6. var obj = {
  7. name: "why",
  8. foo: foo
  9. }
  10. foo() // undefined
  11. obj.foo() // obj
  12. var bar = obj.foo
  13. bar() // undefined
  14. // setTimeout的this
  15. // fn.apply(this = window)
  16. setTimeout(function() {
  17. console.log(this) // window
  18. }, 1000);

===================

箭头函数 ( ) => { }

基本

image.png
箭头函数未被提升。它们必须在使用前进行定义。
image.png
image.png
image.png (但是NodeJS环境里是有的,每个文件是一个模块,这样显示的就是这个模块的arguments)

优化(简写)

image.png

应用场景

image.png image.png
image.png image.png
image.png

面试题

  1. var name = 'window'
  2. var person1 = {
  3. name: 'person1',
  4. foo1: function () {
  5. console.log(this.name)
  6. },
  7. foo2: () => console.log(this.name),
  8. foo3: function () {
  9. return function () {
  10. console.log(this.name)
  11. }
  12. },
  13. foo4: function () {
  14. return () => {
  15. console.log(this.name)
  16. }
  17. }
  18. }
  19. var person2 = { name: 'person2' }
  20. // person1.foo1(); // person1(隐式绑定)
  21. // person1.foo1.call(person2); // person2(显示绑定优先级大于隐式绑定)
  22. // person1.foo2(); // window(不绑定作用域,上层作用域是全局)
  23. // person1.foo2.call(person2); // window
  24. // person1.foo3()(); // window(独立函数调用)
  25. // person1.foo3.call(person2)(); // window(独立函数调用)
  26. // person1.foo3().call(person2); // person2(最终调用返回函数式, 使用的是显示绑定)
  27. // person1.foo4()(); // person1(箭头函数不绑定this, 上层作用域this是person1)
  28. // person1.foo4.call(person2)(); // person2(上层作用域被显示的绑定了一个person2)
  29. // person1.foo4().call(person2); // person1(上层找到person1)