如何理解和使用 this 关键字

news2024/11/17 5:44:34

this 关键字是许多编程语言中的一个核心概念,在面向对象编程(OOP)中尤为重要。在JavaScript、Java、C++、C#等语言中,this 扮演着至关重要的角色。理解 this 的意义和用法,对于编写清晰、有效的代码至关重要。

什么是this

简单来说,this 关键字在面向对象编程中指代的是“当前对象”——即方法或函数被调用时所关联的对象。this 的具体值根据其上下文而变化,可以指代不同的对象。理解和正确使用 this 是编写灵活、重用代码的基础。

JavaScript中的this

全局上下文中的this

在全局上下文(即非严格模式下的全局代码)中,this 指向全局对象。对于浏览器中的JavaScript,全局对象是 window

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

在严格模式下,全局上下文中的 thisundefined

"use strict";
console.log(this); // undefined
函数上下文中的this

在函数调用中,this 的值取决于函数的调用方式。

  • 普通函数调用: 在非严格模式下,this 依然指向全局对象。
function foo() {
  console.log(this);
}
foo(); // 在浏览器中,this 指向 window
  • 严格模式下的函数调用: thisundefined
"use strict";
function foo() {
  console.log(this);
}
foo(); // undefined
方法调用中的this

当方法作为对象的属性调用时,this 指向调用该方法的对象。

const obj = {
  name: 'Alice',
  greet: function() {
    console.log(this.name);
  }
};

obj.greet(); // 'Alice'
构造函数中的this

构造函数是一种特殊的函数,用于创建对象。使用 new 操作符调用构造函数时,this 指向新创建的对象。

function Person(name) {
  this.name = name;
}

const person1 = new Person('Alice');
console.log(person1.name); // 'Alice'
箭头函数中的this

箭头函数在定义时绑定 this,其值为定义时所在上下文的 this,而不是调用时的 this。这是与传统函数的一个显著区别。

const obj = {
  name: 'Alice',
  greet: function() {
    const inner = () => {
      console.log(this.name);
    };
    inner();
  }
};

obj.greet(); // 'Alice'

在上例中,箭头函数 innerthis 绑定在 greet 方法定义时的 this,即 obj

Java中的this

类的实例方法中的this

在Java中,this 关键字在实例方法中指代当前对象。

public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }

  public void greet() {
    System.out.println("Hello, " + this.name);
  }

  public static void main(String[] args) {
    Person person = new Person("Alice");
    person.greet(); // Hello, Alice
  }
}

在上例中,this.name 访问的是当前对象的 name 属性。

构造器中的this

在构造器中,this 也指向当前对象。构造器可以调用类中的另一个构造器,这称为构造器链(constructor chaining)。

public class Person {
  private String name;
  private int age;

  public Person(String name) {
    this(name, 0); // 调用另一个构造器
  }

  public Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
}
匿名类中的this

在Java中,匿名类是没有名字的内部类。匿名类中的 this 关键字指向匿名类的实例,而不是包含匿名类的外部类的实例。

public class Outer {
  private String name = "Outer";

  public void createInner() {
    new Thread(new Runnable() {
      private String name = "Inner";
      public void run() {
        System.out.println(this.name); // Inner
      }
    }).start();
  }

  public static void main(String[] args) {
    Outer outer = new Outer();
    outer.createInner();
  }
}

C++中的this

在C++中,this 是一个指向当前对象的指针。

类的成员函数中的this

在成员函数中,this 指向当前对象。

class Person {
  std::string name;
public:
  Person(std::string name) : name(name) {}

  void greet() {
    std::cout << "Hello, " << this->name << std::endl;
  }
};

int main() {
  Person person("Alice");
  person.greet(); // Hello, Alice
}
链式调用

C++中的 this 指针可以用于返回对象本身,以支持链式调用(method chaining)。

class Person {
  std::string name;
public:
  Person& setName(const std::string& name) {
    this->name = name;
    return *this;
  }

  void greet() const {
    std::cout << "Hello, " << this->name << std::endl;
  }
};

int main() {
  Person person("Alice");
  person.setName("Bob").greet(); // Hello, Bob
}

C#中的this

在C#中,this 关键字用于引用当前实例。

实例方法中的this

在实例方法中,this 指向当前对象。

public class Person {
  private string name;

  public Person(string name) {
    this.name = name;
  }

  public void Greet() {
    Console.WriteLine("Hello, " + this.name);
  }

  public static void Main(string[] args) {
    Person person = new Person("Alice");
    person.Greet(); // Hello, Alice
  }
}
构造函数中的this

C#中,构造函数可以通过 this 关键字调用另一个构造函数。

public class Person {
  private string name;
  private int age;

  public Person(string name) : this(name, 0) { }

  public Person(string name, int age) {
    this.name = name;
    this.age = age;
  }
}
扩展方法中的this

在C#中,扩展方法允许我们向现有类型添加方法,而无需创建新的派生类型。扩展方法的第一个参数是 this,表示被扩展的类型实例。

public static class PersonExtensions {
  public static void Introduce(this Person person) {
    Console.WriteLine("My name is " + person.Name);
  }
}

public class Person {
  public string Name { get; set; }
}

public class Program {
  public static void Main() {
    Person person = new Person { Name = "Alice" };
    person.Introduce(); // My name is Alice
  }
}

this 关键字的实际应用

避免命名冲突

在构造函数和方法中,this 常用于避免命名冲突。例如,当参数名称与成员变量名称相同时,可以使用 this 区分二者。

public class Person {
  private String name;

  public Person(String name) {
    this.name = name; // 使用 this 区分成员变量和参数
  }
}
方法链(Method Chaining)

通过返回 this,我们可以在同一对象上连续调用多个方法,实现方法链。

class Person {
  constructor(name) {
    this.name = name;
  }

  setName(name) {
    this.name = name;
    return this;
  }

  greet() {
    console.log("Hello, " + this.name);
    return this;
  }
}

const person = new Person('Alice');
person.setName('Bob').greet(); // Hello, Bob
事件处理程序中的this

在JavaScript中,事件处理程序常使用 this 访问触发事件的元素。

<button id="btn">Click me</button>

<script>
  document.getElementById('btn').addEventListener('click', function() {
    console.log(this.id); // btn
  });
</script>
this 在回调函数中的使用

在回调函数中,this 的值可能不如预期。这种情况下,可以使用 .bind() 方法明确绑定 this,或者使用箭头函数。

const obj = {
  name: 'Alice',
  greet: function() {
    setTimeout(function() {
      console.log(this.name); // undefined,因为 this 指向全局对象
    }.bind(this), 1000);
  }
};

obj.greet(); // Alice

或使用箭头函数:

const obj = {
  name: 'Alice',
  greet: function() {
    setTimeout(() => {
      console.log(this.name); // Alice,因为箭头函数不会绑定自己的 this
    }, 1000);
  }
};

obj.greet(); // Alice

this 关键字在不同的编程语言中具有类似的概念,但其具体行为和使用场景可能有所不同。在JavaScript中,this 的值取决于函数的调用方式,使用不当可能导致意外结果。而在Java、C++、C#等语言中,this 通常更为直观,指代当前实例。

理解 this 的关键在于清楚其在不同上下文中的指代对象,通过实际应用和实践,可以更好地掌握和利用这一重要概念,提高代码的可读性和可维护性。

黑马程序员免费预约咨询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1712543.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字符串操作:写一个方法,实现字符串的反转,如:输入abc,输出cba

import java.util.Scanner; public class Test_A15 {public static void main(String[] args){String strA"";System.out.println("请输入一串字符串:");Scanner scannernew Scanner(System.in);strAscanner.next();Test_A15 T15new Test_A15();String re…

JAVA系列:NIO

NIO学习 一、前言 先来看一下NIO的工作流程图&#xff1a; NIO三大核心组件&#xff0c;channel&#xff08;通道&#xff09;、Buffer&#xff08;缓冲区&#xff09;、selector&#xff08;选择器&#xff09;。NIO利用的是多路复用模型&#xff0c;一个线程处理多个IO的读…

新时代病毒侵染了全世界!自律的自我认知,无聊才是根本——早读(逆天打工人爬取热门微信文章解读)

刷视频的动作是什么&#xff1f; 引言Python 代码第一篇 【夜读】为什么要自律&#xff1f;这是我听过最走心的答案第二篇结尾 引言 文字阅读数量确实在缩减 虽然我觉得未来还是有一席之地 当下的人 普罗大众吧 你让他们看书 看文字 显然是不现实的 他们比起看书看文字 更喜欢…

光缆监测主要设备是什么?

光功率计&#xff08;OPM&#xff09;稳定光源&#xff1a; 当被测光照射到光检测器上即产生相应的光电流&#xff0c;主机部分的作用是把检测到的电信号放大和模/数变换后进入CPU,经CPU处理后的数字信号最后以光功率或相应的功率电平形式显示出来。 光时域反射仪&#xff08;…

GaN功率电子器件中体缺陷相关机制的建模仿真研究

在电力电子器件的外延生长和器件制备过程中&#xff0c;缺陷是不可避免的&#xff0c;大量的缺陷在一定程度上会牺牲器件的击穿电压、导通电阻等性能&#xff0c;同时影响器件的可靠性。近期&#xff0c;河北工业大学和广东工业大学联合开发了缺陷相关的仿真模型&#xff0c;深…

解决Springboot服务启动报错:“Reason: Failed to determine suitable jdbc url”

1、错误详情 *************************** APPLICATION FAILED TO START *************************** Description: Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine sui…

在全志H616核桃派开发板上配置SSH远程终端方法详解

熟悉指令用户可以对已经联网的核桃派进行局域网SSH远程终端控制&#xff0c;方便使用自己的PC对核桃派远程进行各种指令操作。 普通用户&#xff08;默认&#xff09; 账号&#xff1a;pi ; 密码&#xff1a;pi管理员账户 账号&#xff1a;root ; 密码&#xff1a;root 在这之…

Java基础-注解

注解本质是继承了Annotation接口的一个接口 首先&#xff0c;我们通过键值对的形式可以为注解属性赋值&#xff0c;像这样&#xff1a;Hello&#xff08;value “hello”&#xff09;。 接着&#xff0c;你用注解修饰某个元素&#xff0c;编译器将在编译期扫描每个类或者方…

1794 jsp蛋糕店管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 蛋糕店管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助采用了java设计&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统采用web模式&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&…

swagger-ui页面接口的入参出参与代码实体类不一致有差异、swagger请求实体与预期定义不符、swagger参数与实体中参数不一致原因分析

文章目录 一、问题背景二、问题原因及解决方法 一、问题背景 项目集成swagger之后&#xff0c;发现有个接口的请求跟接口对应不上&#xff0c;把其他接口的请求参数放到当前这个请求上了。 如下图&#xff1a;test1接口的请求参数是其他请求的&#xff0c;并不是test1接口的 …

【Qt】[001]-从入门到成神-前言

一、Qt是什么&#xff1f;[概念] Qt是一个跨平台的应用程序开发框架&#xff0c;简单来说&#xff0c;它是一套工具和库&#xff0c;帮助软件开发者编写可以在多种操作系统上运行的图形用户界面&#xff08;GUI&#xff09;应用程序。比如&#xff0c;你用Qt写了一个软件&#…

ChatGPT:轻松搞定论文润色,让语言更流畅

GPT从3.5一路升级到4.0&#xff0c;不仅在国外火得一塌糊涂&#xff0c;还悄悄地在我们论文润色的世界里掀起了一场革命。 首先&#xff0c;得承认&#xff0c;虽然这玩意儿是“洋货”&#xff0c;用起来可能得费点脑筋——注册个账号啦&#xff0c;买个会员啦之类的。但它对我…

充电宝哪家好用?西圣、倍思、小米充电宝哪个好?热门品牌实测

在如今充电宝市场中&#xff0c;充电宝已经深受大家的喜爱了&#xff0c;但是在市面上众多充电宝中&#xff0c;西圣、倍思、小米充电宝无疑是其中的佼佼者&#xff0c;那么&#xff0c;面对三款热门品牌的充电宝我们该如何选择呢&#xff1f;作为一个有着选购充电宝的老司机来…

赛氪网与武汉外语外事职业学院签署校企合作,共创职业教育新篇章

5月23日下午14:00&#xff0c;武汉外语外事职业学院在藏龙岛校区食堂三楼报告厅隆重举行了2024年职业教育活动周优秀校外实习基地表彰仪式。本次活动旨在表彰在职业教育领域作出突出贡献的校外实习基地&#xff0c;同时加强校企合作&#xff0c;共同推动职业教育的发展。作为重…

香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试(三)

整期笔记索引 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;一&#xff09; 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;二&#xff09; 香橙派OrangePi AIpro上手笔记——之USB摄像头目标检测方案测试&#xff08;…

【深入学习Redis丨第一篇】Redis服务器部署详解

前言 小伙伴们大家好&#xff0c;我是陈橘又青&#xff0c;今天起 《深入学习Redis》 专栏开始更新。本专栏将专为希望深入了解Redis的开发者、系统架构师以及数据库爱好者而写的免费专栏。从Redis的基本概念入手&#xff0c;逐步深入到其内部实现和高级用法。希望能帮助你更好…

uni-app基础框架搭建(vue3+ts+vite)

1.基础准备 uni-app官网uni-app,uniCloud,serverless,环境安装,创建uni-app,自定义模板,国内特殊情况,更新依赖到指定版本,运行、发布uni-app,运行并发布快应用,运行并发布快应用(webview),运行并发布快应用(webview)-华为,cli创建项目和HBuilderX可视化界面创https://uniapp.…

LuatOS学习

开发顺序 Lua是脚本语言中运行速度最快的语言 资源占用极低 脚本语言运行方式 脚本语言是从上往下一行一行运行的 变量 coun 123456 a,b,c 1,2,3交换 a,b b,a在测试环境中&#xff0c;用print(a,b)打印 nil类型 未声明的变量就是nil&#xff0c;nil用来表示此变量为空…

Midjourne进阶篇 | 个性化潮玩

当Midjourney遇上潮玩&#xff0c;你想不到的惊艳&#xff01; 前言盲盒魔法公式**01.嘻哈潮玩****02.荧光猫少女****03.古风剑侠****04.音乐节少年****05.Q版古风少女** 总结 前言 以前&#xff0c;制作盲盒需要专业盲盒设计师完成&#xff0c;对于大部分人来说&#xff0c;这…

柔性自驱动生物“电子衣”促进伤口愈合

引用信息 文 章&#xff1a;Combined Amniotic Membrane and Self-Powered Electrical Stimulator Bioelectronic Dress Promotes Wound Healing 期 刊&#xff1a;ACS Applied Materials & Interfaces&#xff08;影响因子&#xff1a;9.5&#xff09; 发表时间…