首页/文章/javascript

一篇弄清楚JavaScript中的 this到底指向谁

2024-07-15
11924 分钟
...

为什么要有this

1.为了让对象中的函数有能力访问对象自己的属性。

例子

如果我们想要在对象内部方法中使用对象内部的属性,就像图中的代码,它是可以在C语言里运行的,但是在JS中不可行,JS它需要使用this机制来访问(图中的myName)

let obj = {
    myName: '喜羊羊',
    age: 12,
    bar: function () { 
        console.log(this.myName);
    }
}
obj.bar();

2.this可以显著的提升代码质量,减少上下文参数的传递。

这种显示传参的方法有点啰嗦,如果我们采用this的话,那么就会优雅,方便很多。

function identify() {
    return this.name.toUpperCase();
}

function speak() {
    var greeting = 'Hello, I am ' + identify.call(this);
    console.log(greeting);
}

var me = {
    name: 'gg bond'
}

speak.call(me);

运行结果是一样的

this的使用场景

可以产生作用域的地方就可以用this(除了块级作用域)

也就是:

  1. 全局
  2. 函数体内
console.log(this);

在node里打印出来是:

因为node的全局是global空对象,跟浏览器的引擎有些不一样,我们看在浏览器上的运行:

全局代指的是Window

this 代指某一块作用域

写在全局下面就代指全局的作用域

this的绑定规则

1. 默认绑定

当一个函数直接独立调用,不带任何修饰符时,使用默认绑定。 - 函数在哪个词法作用域中生效,函数中的this就指向哪里。(只要是默认绑定this一定指向全局对象window。

function foo() {
    console.log(this);
}
foo();
function foo() {
    console.log(this);
}
function bar() {
    foo();
}
bar()

var

在全局,通过var声明的变量相当于window.xxx,在window对象上添加了一个属性在函数中,通过var声明的变量相当于函数的词法作用域。

let就不会

2. 隐式绑定

当函数的引用有上下文对象时(当函数被某个对象所拥有时),隐式绑定。 - 函数中的this指向的是引用它的对象。

var obj = {
  a: 1,
  foo: foo
}

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

obj.foo()

3. 隐式丢失

当一个函数被赋值被多个对象链式调用时,函数的this指向就近的那个对象

我附庸的附庸不是我的附庸
var obj = {
  a: 1,
  foo: foo
}

var obj2 = {
  a: 2,
  obj: obj
}

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

obj2.obj.foo()

4. 显示绑定

通过bind、apply、call,将函数的this指向指定的对象。call直接接受参数,apply接受参数需要用数组装起来。

bind()

band()会默认返回一个函数体。

当这个新函数被调用时,它的 this 值会被设置为在 bind() 调用中传递的第一个参数。

function greet(greeting) {
    console.log(greeting + ', ' + this.name);
}

let person = { name: 'GG Bond' };

let greetJohn = greet.bind(person, 'Hello'); 
greetJohn(); 

call()

立即调用一个函数,并允许指定 this 值以及任何需要传递给函数的参数。参数直接列在 call() 后面,不需要用数组包装。

function greet(greeting) {
    console.log(greeting + ', ' + this.name);
}

let person = { name: 'call' };

greet.call(person, 'Hi'); 

apply()

apply() 也立即调用一个函数,但与 call() 不同的是,它的参数需要以数组的形式给出。

var obj = {
    a: 1
}

function foo(x, y) {      
    console.log(this.a, x + y);
}
foo.apply(obj, [1, 2])

6. new绑定

通过new调用函数,将函数的this指向新创建的对象。

创建对象并绑定 this 的过程:

  1. 创建一个新对象:首先,JavaScript 引擎会创建一个全新的空对象。
  2. 设置原型链:新对象的原型(__proto__)会被设置为构造函数的 prototype 属性所指向的对象。
  3. 绑定 this:函数内部的 this 被绑定到这个新创建的对象上。
  4. 执行构造函数:构造函数的代码被执行,this 指向新创建的对象。
  5. 返回新对象:如果构造函数没有显式返回一个对象,则默认返回新创建的对象。如果构造函数返回了一个对象,那么这个返回的对象将覆盖新创建的对象。
function Person(name) {
    this.name = name;
    return {}; 
}
let jane = new Person('Jane');
console.log(jane instanceof Object); 
console.log(jane instanceof Person); 

7. 箭头函数

箭头函数中没有this这个机制,写在箭头函数中的this也是它外层非箭头函数的

function regularFunction() {
    console.log(this);
}


const arrowFunction = () => {
    console.log(this);
};


const obj = {
    name: 'Test',
    regularMethod: function() {
        console.log(this);
    },
    arrowMethod: () => {
        console.log(this);
    }
};


regularFunction();       
arrowFunction();         


obj.regularMethod();     
obj.arrowMethod();       

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
javascript2025-09-18
JavaScript 的多线程能力:Worker
如果你写过一些计算量稍大的 JavaScript 代码,比如图像处理、大量数据排序或者复杂的算法,你几乎肯定遇到过浏览器“卡死”的现象。点击页面没反应,动画也停了,就像整个世界都静止了。 这就是主线程被阻塞的典型后果。因为主线程既要负责执行 JavaScript,又要负责渲染页面、响应用户操作,一旦它被繁重的计算任务占满,就无暇顾及其他,用户体验便直线下降。 这个问题的根源,正是“主线程是单线程的”。那么,如何解决呢? 答案很简单:把这...
学习面试
javascript2025-09-10
手把手教你实现一个EventEmitter
你是不是也遇到过这种情况:代码里各种事件监听和触发,回调函数套了一层又一层,最后自己都理不清哪个事件先触发、哪个后触发了? 别担心,今天我就带你从零开始实现一个自己的事件触发器(EventEmitter),让你彻底掌握事件驱动的精髓,代码清晰度直接提升200%! 为什么要懂EventEmitter? 先说说为什么我们要关心这个。Node.js的核心就是事件驱动,比如文件读写、网络请求,都是通过事件来处理的。不会EventEmitter,...
学习面试
javascript2025-08-09
Web Worker 多线程魔法
你是否曾遇到过网页因为复杂计算而卡顿的情况?今天,让我们一起探索Web Worker的神奇世界,看看如何用多线程技术解决性能瓶颈,并实现流畅的图片压缩功能! 为什么需要Web Worker? 想象一下,你在一个繁忙的餐厅里,只有一位服务员(主线程)负责点餐、上菜、结账所有工作。当客人突然暴增时,这位服务员就会手忙脚乱,其他客人只能干等着… 这就是JavaScript的现状—— 单线程 !所有任务都在一个线程中排队执行,一旦遇到复杂计算(...
学习面试
javascript2025-08-07
🌐AST抽象语法树
AST 是前端开发中一个非常重要的概念,它就像是代码的“编译器”,能够帮助我们理解和操作代码。本文将深入探讨 AST 的原理和应用,带你从零开始了解 AST。 一、什么是 AST? AST(抽象语法树)是一种树形结构,用于表示程序代码的语法结构。它将代码分解为一系列的节点,每个节点代表代码中的一个元素,如变量、函数、表达式等。AST 是编译器和解释器的基础,也是代码分析和转换的关键工具。 1\. AST 的结构 AST 的结构通常包括以...
学习面试
javascript2025-08-05
打字机效果是如何实现的
分析效果 使用 AI 对话的时候,文字是一个字一个字蹦出来的?它不是等所有内容生成完毕后一次性展示,而是以一种流畅、实时的“打字机”效果呈现,这种体验的背后,隐藏着一种高效的Web技术。它就是 服务器推送事件(Server Sent Events,简称 SSE) 什么是 SSE 从根本上说,SSE 是一种允许服务器 单向 、 持续 地向客户端(浏览器)推送数据的Web技术。 可以把它想象成一个 电台广播 : 服务器 是广播电台,持续不断...
学习面试
javascript2025-08-04
Promise 从原理到实现
前言 是 异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。 本文将全面剖析 的工作原理,并逐步实现一个符合 规范的 。 正文 一、Promise 基础概念 代表一个异步操作的最终完成(或失败)及其结果值。它有 种状态: 1. pending : ,既不是成功,也不是失败状态 2. fulfilled :意味着操作 完成 3. rejected :意味着操作 状态一旦改变就不能再变,只能从 变为 ,或从 变为 。 二...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录