当前位置: 首页 > news >正文

JS传统函数中常见的 this 绑定问题

       在 JavaScript 中,传统函数的 this 绑定规则依赖于函数的调用方式,这常常导致一些意外的行为和常见的 this 绑定问题。以下是一些典型的 this 绑定问题及其解决方案。

1. 作为对象方法调用时的 this 丢失

       当一个对象的方法被赋值给一个变量或作为回调函数传递时,this 的值可能会丢失,导致 this 指向全局对象或 undefined(在严格模式下)。

示例
const obj = {name: 'Alice',greet: function() {console.log(`Hello, ${this.name}!`);}
};const greet = obj.greet;
greet(); // 输出: Hello, undefined! (因为 this 指向全局对象)
解决方案
  1. 使用 bind 方法:可以使用 bind 方法来显式地绑定 this

    const obj = {name: 'Alice',greet: function() {console.log(`Hello, ${this.name}!`);}
    };const greet = obj.greet.bind(obj);
    greet(); // 输出: Hello, Alice!
  2. 使用箭头函数:箭头函数没有自己的 this 绑定,会继承其词法作用域中的 this

    const obj = {name: 'Alice',greet: function() {console.log(`Hello, ${this.name}!`);}
    };const greet = () => obj.greet();
    greet(); // 输出: Hello, Alice!

2. 在回调函数中 this 的值不正确

       在使用定时器、事件监听器或其他异步操作时,回调函数中的 this 可能会指向错误的对象。

示例
const obj = {name: 'Alice',greet: function() {setTimeout(function() {console.log(`Hello, ${this.name}!`); // 这里的 this 指向全局对象}, 1000);}
};obj.greet(); // 1秒后输出: Hello, undefined!
解决方案
  1. 使用 bind 方法:可以使用 bind 方法来显式地绑定 this

    const obj = {name: 'Alice',greet: function() {setTimeout(function() {console.log(`Hello, ${this.name}!`);}.bind(this), 1000);}
    };obj.greet(); // 1秒后输出: Hello, Alice!
  2. 使用箭头函数:箭头函数没有自己的 this 绑定,会继承其词法作用域中的 this

    const obj = {name: 'Alice',greet: function() {setTimeout(() => {console.log(`Hello, ${this.name}!`);}, 1000);}
    };obj.greet(); // 1秒后输出: Hello, Alice!

3. 作为构造函数调用时的 this 问题

       虽然构造函数中的 this 通常指向新创建的实例对象,但在某些情况下,如果不使用 new 关键字调用构造函数,this 会指向全局对象。

示例
function Person(name) {this.name = name;
}const p = Person('Bob'); // 忘记使用 new 关键字
console.log(p); // undefined
console.log(window.name); // 输出: Bob
解决方案
  1. 检查 new.target:可以使用 new.target 来检测函数是否作为构造函数调用。

    function Person(name) {if (!new.target) {throw new Error('Person must be called with new');}this.name = name;
    }try {const p = Person('Bob'); // 抛出错误: Person must be called with new
    } catch (e) {console.error(e.message);
    }const p2 = new Person('Bob'); // 正确调用
    console.log(p2.name); // 输出: Bob

4. 在事件处理程序中 this 的值不正确

       在事件处理程序中,this 通常指向触发事件的元素,而不是预期的对象。

示例
const button = document.createElement('button');
button.textContent = 'Click me';
document.body.appendChild(button);const obj = {name: 'Alice',handleClick: function(event) {console.log(`Button clicked by ${this.name}`); // 这里的 this 指向按钮元素}
};button.addEventListener('click', obj.handleClick);
解决方案
  1. 使用 bind 方法:可以使用 bind 方法来显式地绑定 this

    const button = document.createElement('button');
    button.textContent = 'Click me';
    document.body.appendChild(button);const obj = {name: 'Alice',handleClick: function(event) {console.log(`Button clicked by ${this.name}`);}
    };button.addEventListener('click', obj.handleClick.bind(obj));
  2. 使用箭头函数:箭头函数没有自己的 this 绑定,会继承其词法作用域中的 this

    const button = document.createElement('button');
    button.textContent = 'Click me';
    document.body.appendChild(button);const obj = {name: 'Alice',handleClick: () => {console.log(`Button clicked by ${this.name}`);}
    };button.addEventListener('click', obj.handleClick);

5. 在类方法中 this 的值不正确

       在类方法中,如果方法被赋值给一个变量或作为回调函数传递,this 的值可能会丢失。

示例
class Person {constructor(name) {this.name = name;}greet() {console.log(`Hello, ${this.name}!`);}
}const person = new Person('Alice');
const greet = person.greet;
greet(); // 输出: Hello, undefined! (因为 this 指向全局对象)
解决方案
  1. 使用 bind 方法:可以在构造函数中使用 bind 方法来显式地绑定 this

    class Person {constructor(name) {this.name = name;this.greet = this.greet.bind(this);}greet() {console.log(`Hello, ${this.name}!`);}
    }const person = new Person('Alice');
    const greet = person.greet;
    greet(); // 输出: Hello, Alice!
  2. 使用箭头函数:可以在类方法中使用箭头函数来避免 this 绑定问题。

    class Person {constructor(name) {this.name = name;}greet = () => {console.log(`Hello, ${this.name}!`);}
    }const person = new Person('Alice');
    const greet = person.greet;
    greet(); // 输出: Hello, Alice!

总结

      传统函数中的 this 绑定问题主要集中在以下几个方面:

          1. 作为对象方法调用时的 this 丢失:可以通过 bind 方法或箭头函数解决。

          2. 在回调函数中 this 的值不正确:可以通过 bind 方法或箭头函数解决。

          3. 作为构造函数调用时的 this 问题:可以通过检查 new.target 来解决。

          4. 在事件处理程序中 this 的值不正确:可以通过 bind 方法或箭头函数解决。

          5. 在类方法中 this 的值不正确:可以通过 bind 方法或箭头函数解决。

      理解这些常见的 this 绑定问题及其解决方案,可以帮助你编写更可靠和维护性更好的代码。

相关文章:

JS传统函数中常见的 this 绑定问题

在 JavaScript 中,传统函数的 this 绑定规则依赖于函数的调用方式,这常常导致一些意外的行为和常见的 this 绑定问题。以下是一些典型的 this 绑定问题及其解决方案。 1. 作为对象方法调用时的 this 丢失 当一个对象的方法被赋值给一个变量或作为回调函…...

跨域问题以及使用vscode的LiveServer插件跨域访问

目录 现象跨域问题的定义(文心一言)解决办法同源部署后端代理VS Code LiveServer 现象 以下前端代码部署后,在网页访问时报错:No ‘Access-Control-Allow-Origin’ header is present on the requested resource. $.ajax({url:…...

现代Web开发:WebSocket 实时通信详解

💓 博客主页:瑕疵的CSDN主页 📝 Gitee主页:瑕疵的gitee主页 ⏩ 文章专栏:《热点资讯》 现代Web开发:WebSocket 实时通信详解 现代Web开发:WebSocket 实时通信详解 现代Web开发:WebS…...

《深度学习》——深度学习基础知识(全连接神经网络)

文章目录 1.神经网络简介2.什么是神经网络3.神经元是如何工作的3.1激活函数3.2参数的初始化3.2.1随机初始化3.2.2标准初始化3.2.3Xavier初始化(tf.keras中默认使用的)3.2.4He初始化 4.神经网络的搭建4.1通过Sequential构建神经网络4.2通过Functional API…...

nginx 部署2个相同的vue

起因: 最近遇到一个问题,在前端用nginx 部署 vue, 发现如果前端有改动,如果不适用热更新,而是直接复制项目过去,会404 因此想到用nginx 负载两套相同vue项目,然后一个个复制vue项目就可以了。…...

利用Java easyExcel库实现高效Excel数据处理

在Java应用程序中,处理Excel文件是一项常见任务,尤其是在需要读取、写入或分析大量数据时。easyExcel是一个基于Java的高性能Excel处理库,它提供了简洁的API和优化的性能,以简化Excel文件的处理。本文将指导您如何使用easyExcel库…...

Vulnhub靶场 Metasploitable: 1 练习(上)

目录 0x00 准备0x01 主机信息收集0x02 Samba服务(CVE-2007-2447)0x03 Distccd(CVE-2004-2687)0x04 Mysql弱口令0x05 Postgresql弱口令0x06 Telnet弱口令0x07 Tomcat 0x00 准备 下载链接:https://download.vulnhub.com/…...

《Python编程实训快速上手》第二天--列表与元组

一、列表 1、理解 列表是一个值,包含由多个值构成的序列 2、元素查找 1)索引--取列表中的单个值 正数索引:同c语言中的数组 spam [[1,2,3,4],["cat","dog"]] print(spam[0][1]) #结果:2 负数索引&…...

jangow靶机

先改jangow的ip设置,无ip地址,重启jangow虚拟机时候快速按E这个键盘,进入到编辑模式,找到ro这个位置,写入ro rw signin init/bin/bash ​,ctrlx保存 下一步需要更改网卡名字为ens33,可以直接…...

使用UDP协议传输视频流!(分片、缓存)

背景 最近在开发工作中遇到需要两台本地设备之间进行视频流的传输的情况。但是团队一来没有这方面的专业人才,二来视频流的传续数据量很大,针对TCP和UDP的具体选择也不明确。 本文是在上诉背景之下进行的研究和开发工作。 目录 背景 UDP和TCP协议的…...

Pinia小菠萝(状态管理器)

Pinia 是一个专为 Vue 3 设计的状态管理库,它借鉴了 Vuex 的一些概念,但更加轻量灵活。下面将详细介绍如何使用 Pinia 状态管理库: 安装 Pinia 使用 npm:在项目目录下运行npm install pinia。使用 yarn:在项目目录下运…...

Python知识点:基于Python工具,如何使用Web3.py进行以太坊智能合约开发

开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 基于Python工具Web3.py进行以太坊智能合约开发 简介 智能合约是区块链技术的核…...

【简信CRM-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...

ssm+vue694基于Java的药店药品信息管理系统的设计与实现

博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…...

Sentinel微服务保护

目录 雪崩问题 解决雪崩问题的方法: 我们使用sentinel组件实现微服务的保护 一:下载sentinel 二.启动sentinel 三.访问:localhost:8080 默认的账号和密码都是sentinel 微服务整合sentinel 一.导入sentinel依赖 二.在application.yml配置…...

喜讯!实在Agent智能体入选《2024年度最佳企业服务AI产品榜》

10 月 30 日,硅星人主办的首届 AI 创造者大会(ACC)于北京中关村盛大举行。此次大会旨在为 AI 产业生态的共建者构筑一个多元化的交流平台。大会邀请了硅星人创始人兼 CEO 骆轶航、国家地方共建具身智能机器人创新中心 CTO 唐剑、百度智能云应…...

Aop+自定义注解实现数据字典映射

数据字典 Web项目开发中,字典表的一般都会存在,主要用来给整个系统提供基础服务。 比如男女性别的类型可以使用0和1来进行表示,在存储数据和查询数据的时候,就可以使用字典表中的数据进行翻译处理。 再比如之前做的一个项目中宠物…...

大语言模型(LLM)入门级选手初学教程 III

指令微调 一、指令数据的构建 包括任务描述(也称为指令)、任务输入-任务输出以及可选的示例。 Self-Instruct 指令数据生成:从任务池中随机选取少量指令数据作为示例,并针对Chat-GPT 设计精细指令来提示模型生成新的微调数据…...

STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入

STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次写入 参考例程例程说明一、存储到Flash中的数据二、Flash最底层操作(解锁,加锁,擦除,读写)三、从Flash块中读取数据五、测试验证 参考例程 STM32G0xx HAL和LL库Flash读写擦除操…...

SAP B1 认证考试习题 - 解析版(三)

前一篇:《SAP B1 认证考试习题 - 解析版(二)》 题目纯享版合集:《SAP B1 认证考试习题 - 纯享版》 五、运费(附加费用) 57. 以下哪个选项能够影响库存商品的价格 A. 仅为总量级别的附加费用 B. 只为行级…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

如何为服务器生成TLS证书

TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

LLM基础1_语言模型如何处理文本

基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

ios苹果系统,js 滑动屏幕、锚定无效

现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

AspectJ 在 Android 中的完整使用指南

一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...