day 04 JS this 问题

133 阅读2分钟

this有四种绑定规则

  • 默认绑定规则

在全局当中以及在函数的独立调用(说白了就是调用此函数的时候和 window.fn()的效果一样) 那么 this 默认指向window

console.log(this === window) // true;

function fn () {
    console.log(this === window)
}
fn() //true
  • 隐式绑定规则 (谁调用就指向谁)
const a = 1;
const obj = {
    a: 2,
    fn: function () {
        console.log(this)
    }
}

obj.fn(); // obj
/* ································································· */

如果fn是箭头函数的话,打印出来的是window
const a = 1;
const obj = {
    a: 2,
    fn: function () {
        console.log(this) // obj
        function test () {
            console.log(this) // window
        }
        test()
    }
}

这里的test()相当于一个立即执行函数,立即执行函数的this一定是指向对应的全局变量,在浏览器中是window,在node中是global

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

function bar (fn) {
    fn()
}

var obj = {
    a: 2,
    foo: foo
}
bar(obj.foo)

父函数是有能力去改变子函数内的this值得 new fn() call apply bind

高阶函数

比如 forEach(fn, [thisArg]) 第二次参数就是fn内this的值。 一般的API接口里都是有指明的。

  • 显式绑定 call apply bind 就是为了更改this而存在的。强行改变this执行

image.png

传参的方式不一样

  • new 绑定 this 指向实例

这里再延申一下 new 一个对象发生了什么

使用 new 操作符实例化 Person 的操作等于使用 new 调用其构造函数。唯一可感知的不同之处就是, JavaScript 解释器知道使new和类意味着应该使用 constructor 函数进行实例化。使用 new 调用类的构造函数会执行如下操作。

  1. 在内存中创建一个新对象。
  2. 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。
  3. 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)。
  4. 执行构造函数内部的代码(给新对象添加属性)。
  5. 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。 摘自 《JavaScript高级程序设计(第4版)》

this 指向还存在一个优先级的问题,顺序就是本笔记的顺序new > 显式 > 隐式 > 默认