【JS】this 是啥?

118 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

新年快乐!

前言

this 关键字是 JavaScript 中的一个重点,它是一个特别的关键字,代表了当前的上下文。

在面试时,关于 this 的题目也是经常出现。在学习源码或别人的代码时,搞懂 this 关键字对我们对代码的理解能起到很大的帮助。

this 的绑定规则

默认绑定

普通函数的调用(不带任何修饰的调用),此时 this 指向全局对象 window。 若函数声明时使用严格模式,则 this 指向 undefined

如下代码,在调用函数 test 时,应用了默认绑定(非严格模式),此时的 this 指向全局对象。

function test() {
    console.log(this.name);
}

var name = 'hhhqzh';
test(); // 'hhhqzh'

如下代码,在函数声明时使用了严格模式,此时 this 指向 undefined,会报错。

function test() {
    'use strict';
    console.log(this.name);
}

var name = 'hhhqzh';
test(); 

图片.png

隐式绑定

当函数有引用上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到函数执行上下文。简单来说就是通过对象来调用其函数。

function test(){
    console.log(this.name); 
} 

var person = {
    name: 'ppptyp', 
    test: test 
} 

var name = 'hhhqzh';
person.test(); // 'ppptyp'

test 函数声明在外部,严格来说并不属于 person 这个对象,但是在调用 test 时,调用位置会使用 person 的上下文来引用函数,隐式绑定会把函数调用中的 this(即此例 test 函数中的 this)绑定到这个上下文对象(即此例中的 person),所以最后的运行结果是 'ppptyp' 而不是 'hhhqzh'。

  • 隐式丢失 隐式丢失是隐式绑定的一个小缺陷,即隐式绑定的函数丢失绑定对象,引用默认绑定

比如:直接把函数作为参数传递或变量赋值,这时引用的只是函数本身。

var person = {
    name: 'ppptyp', 
    test: function test(){
        console.log(this.name); 
    }  
} 

var name = 'hhhqzh';
var fn = person.test;
fn(); // 'hhhqzh'

person 对象的 test 函数赋值给变量 fn,此时 fn 直接指向了 test 的引用,在调用的时候与 person 没有关系,此时的 this 使用的是默认绑定,指向全局对象 window

显式绑定

  • 通过使用 callapplybind 改变 this 的行为。

    callapplybind的第一个参数,就是对应函数的 this 所指向的对象,bind 属于硬绑定,即绑定后返回的函数的 this 无法再次使用显示绑定进行修改。

function test() {
    console.log(this.name);
}

var name = 'person';
var person = {
    name: 'hhhqzh'
}
test.apply(person); // 'hhhqzh'

使用了显示绑定把 this 绑定到了 person 上。

  • API 调用的上下文

比如 mapforEach 等可以把对象作为参数并把它当做函数执行时的 this 的 API。

new

【JS】单身狗:怎样才能 new 一个对象呢?

在 JavaScript 中,构造函数只是使用 new 操作符时被调用的函数,这些函数和普通的函数是一样的,它不是面向对象语言中的类。任何一个函数都可以使用 new 来调用。

new 关键字会进行以下四步的操作,因此使用 new 来创建新对象的时候,会将新对象绑定到构造函数的 this

  • 创建一个空的简单JavaScript对象(即{});
  • 为新创建的空对象添加属性 proto ,将该属性链接至构造函数的原型对象;
  • 将新创建的对象作为this的上下文;
  • 如果该函数没有返回对象,则返回this,否则返回函数返回的对象。
function test(name){
    this.name = name;
	
}
var my = new test('hhhqzh');
console.log(my.name); // 'hhhqzh'

箭头函数

  • 箭头函数的 this 指向在定义的时候继承自外层作用域的 this

    • 一旦箭头函数的 this 绑定成功,无法被直接修改(callapplybind 都无法进行绑定)
    • 通过修改箭头函数外层作用于的 this 指向间接修改
    • 箭头函数外层没有普通函数,严格模式和非严格模式下它的 this 都会指向 window (全局对象)
  • 箭头函数没有原型 prototype,所以箭头函数本身没有 this

  • 箭头函数没有 argumens,其 argumens 继承自外层作用域的 argumens,若箭头函数的 this 指向 window,则没有 argumens

  • 箭头函数不能被 new,因为没有 constructor

  • 箭头函数没有 new.target (ES6, 使用 new 调用函数,new.target 指向类本身,普通调用就是 undefined, 可以用来判断是否使用了 new)

最后

欢迎大家在评论区一起交流,一起进步!