JavaScript(9) ----this指向问题,bind,call,apply等方法

news2024/9/21 4:40:48

目录

this指向问题

全局函数调用:

对象方法调用:

构造函数调用:

事件处理:

箭头函数:

setTimeout和setInterval

7.使用call、apply或bind

call 方法

apply 方法

bind 方法

总结


this指向问题

  • 全局函数调用:在全局作用域中调用函数时,this指向全局对象(浏览器中是window对象)。

function sayHello() {
    console.log(this);
}
sayHello(); // 输出:Window {...}
  • 对象方法调用:当函数作为对象的方法被调用时,this指向调用该方法的对象。


const person = {
    name: 'Alice',
    greet: function() {
        console.log('Hello, ' + this.name);
    }
};
person.greet(); // 输出:Hello, Alice
  • 构造函数调用:使用new关键字创建对象时,this指向新创建的对象。

function Person(name) {
    this.name = name;
}
const bob = new Person('Bob');
console.log(bob.name); // 输出:Bob
  • 事件处理:在事件处理函数中,this指向触发事件的元素。

<button id="myButton">Click me!</button>
<script>
document.getElementById('myButton').addEventListener('click', function() {
    console.log(this); // 输出:button#myButton
});
</script>
  • 箭头函数:箭头函数没有自己的this上下文,它会捕获其所在上下文的this值,作为自己的this值,除非它是在全局作用域中定义的。

const obj = {
    arr: [1, 2, 3],
    sum: () => {
        return this.arr.reduce((a, b) => a + b, 0);
    }
};
console.log(obj.sum()); // 输出:6
  • setTimeoutsetInterval

在JavaScript中,setTimeout和setInterval函数用于设置定时器,分别用于延迟执行和重复执行指定的函数。与普通函数调用不 同,setTimeout和setInterval中的回调函数不会自动绑定到任何特定的对象上,它们的this值通常指向全局对象(在浏览器中是window对象),除非显式地使用call、apply或bind方法来改变this的值。

function delayedGreeting() {
    console.log('Hello, ' + this.name);
}

const person = { name: 'Dave' };

// 直接使用setTimeout,this将指向全局对象
setTimeout(delayedGreeting, 1000); // 输出:Hello, undefined(因为this.name是undefined)

// 使用bind来绑定this
setTimeout(delayedGreeting.bind(person), 1000); // 输出:Hello, Dave
  • 7.使用call、apply或bind:这些方法允许你显式地设置this的值。

function sayName(name) {
    console.log('My name is ' + this.name + ' and you are ' + name);
}
const person = { name: 'Alice' };
sayName.call(person, 'Bob'); // 输出:My name is Alice and you are Bob

在JavaScript中,call、apply和bind这三个方法都可以用来显式地设置this的值,它们主要区别在于参数传递的方式不同。

call 方法

call方法调用一个函数,将this关键字设置为指定的对象,并在调用时将其余参数逐个传递给该函数。

语法:

functionName.call(thisArg, arg1, arg2, ...);

示例:

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

const person = { name: 'Alice' };

// 使用call方法调用greet函数,将this设置为person对象
greet.call(person, 'Hello', '!'); // 输出:Hello Alice!

// 2. call的应用场景 - 检测数据类型
    // 2.1 typeof 检测数据类型不够精确的
    console.log(typeof '123') // string
    console.log(typeof []) // object
    console.log(typeof null) // object

    // 2.2 Object.prototype.toString()  返回的结果是[object xxx类型]
    // console.log(Object.prototype.toString('123')) //  [object Object]
    console.log(Object.prototype.toString.call('123'))  // [object String]
    console.log(Object.prototype.toString.call(123))  // [object Number]
    console.log(Object.prototype.toString.call([]))  // [object Array]
    console.log(Object.prototype.toString.call(null))  // [object Null]

apply 方法

apply方法与call方法类似,但它接受一个参数数组,而不是多个参数。

语法:

functionName.apply(thisArg, [argsArray]);

示例:


function sum(a, b) {
    console.log(this.name + ' calculates the sum as ' + (a + b));
}

const person = { name: 'Bob' };

// 使用apply方法调用sum函数,将this设置为person对象,并传递参数数组
sum.apply(person, [5, 7]); // 输出:Bob calculates the sum as 12


    // 2. 使用场景- 求数组的最大值/最小值
    console.log(Math.max(...[1, 2, 3]))  // 3

    // apply 或者 call 如果不需要改变this指向 写 null 
    console.log(Math.max.apply(null, [8, 2, 3]))  // 8
    console.log(Math.min.apply(null, [8, 2, 3]))  // 2

bind 方法

bind方法创建一个新的函数,在调用时将this关键字设置为提供的值,第一个参数之后的所有参数都将作为新函数的参数,供调用时使用。

语法:

let boundFunc = functionName.bind(thisArg, arg1, arg2, ...);

示例:

function sayHello() {
    console.log('Hello ' + this.name);
}

const person = { name: 'Carol' };

// 使用bind方法创建一个新的函数,将this设置为person对象
const sayHelloToCarol = sayHello.bind(person);

// 调用新创建的函数
sayHelloToCarol(); // 输出:Hello Carol


    // 2. 使用场景 - 不需要调用函数,但是又想改变函数内部的this指向

    // 1. 发送短信5秒倒计时业务
    const codeBtn = document.querySelector('.code')
    let flag = true  // 开关变量,用来防止多次点击
    codeBtn.addEventListener('click', function () {
      if (flag) {
        // 1.2 利用定时器做倒计时效果 setInterval 
        let i = 5
        // 点击之后立马变化文字
        this.innerHTML = `05秒后重新获取`
        // 定时器
        let timerId = setInterval(function () {
          i--
          this.innerHTML = `0${i}秒后重新获取`

          // 1.3 时间到了 就显示文字为 重新获取
          if (i === 0) {
            this.innerHTML = `重新获取`
            // 停止定时器
            clearInterval(timerId)
            flag = true
          }
        }.bind(this), 1000)
        // 关闭开关 
        flag = false
      }
    })

bind方法返回的是一个新的函数,这意味着你可以将这个新函数赋值给一个变量,或者将它作为回调函数传递给其他函数。

总结

  • call和apply方法都是立即执行函数。
  • call接受参数列表,apply接受一个参数数组。
  • bind返回一个新的函数,可以稍后执行。

这些方法在JavaScript中非常有用,特别是在需要控制函数内部this上下文的场景中。

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

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

相关文章

基于conda包的环境创建、激活、管理与删除

Anaconda是一个免费、易于安装的包管理器、环境管理器和 Python 发行版&#xff0c;支持平台包括Windows、macOS 和 Linux。下载安装地址&#xff1a;Download Anaconda Distribution | Anaconda 很多不同的项目可能需要使用不同的环境。例如某个项目需要使用pytorch1.6&#x…

STM32MP135裸机编程:支持内存非对齐访问

0 前言 使用stm32官方可视化初始化代码生成工具STM32CubeMX生成的工程GCC编译选项默认不支持非对齐访问&#xff0c;在我们进行非对齐的访问时就会进入数据异常中断DAbt中。为了解决这一问题&#xff0c;我们需要在GCC编译选项中加上一处配置。 1 操作方法 右键STM32CubeIDE…

ArkTS基础快速入门

初识ArkTS语言 ArkTS&#xff1a;是一门用于开发鸿蒙应用的编程语言。 ArkTS提供了声明式UI范式、状态管理支持等相应的能力&#xff0c;让开发者可以以更简洁、更自然的方式开发应用。 同时&#xff0c;它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风格的基础…

启动yarn后,其他节点没有NodeManager

写在前面&#xff1a; 这个问题虽然折磨了我两天&#xff0c;但是原因特别蠢&#xff0c;可能与各位不一定一样&#xff0c;我是因为ResourceManager的节点的"/etc/hadoop/workers"文件没有配置好&#xff08;没有配hadoop102和hadoop104&#xff09;&#xff0c;但排…

FPGA学习笔记(一) FPGA最小系统

文章目录 前言一、FPGA最小系统总结 前言 今天学习下FPGA的最小系统一、FPGA最小系统 FPGA最小系统与STM32最小系统类似&#xff0c;由供电电源&#xff0c;时钟电路晶振&#xff0c;复位和调试接口JTAG以及FLASH配置芯片组成&#xff0c;其与STM32最大的不同之处就是必须要有…

QQ频道导航退出

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/140413538 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

three.js添加多个画布

多个场景的渲染需要多个画布&#xff0c;但是这样会导致加载模型纹理次数变多&#xff0c;基本方法是用一张canvas在整个背景中填充视口&#xff0c;利用其它元素作为每个虚拟画布&#xff0c;只在canvas中加载一个渲染器renderer&#xff0c;并为每个虚拟画布创建一个场景&…

实训第一天笔记

#初始化一个新的NPM项目(根据提示操作) npm init #安装TSC、TSLint和NodeJS的类型声明 npm install -s typescript tslint types/node 在根目录中新建一个名为tsconfig.json的文件&#xff0c;然后在代码编辑器中打开&#xff0c;写入下述内容&#xff1a; {"compilerO…

Chromium CI/CD 之Jenkins实用指南2024-如何创建新节点(三)

1. 前言 在前一篇《Jenkins实用指南2024-系统基本配置&#xff08;二&#xff09;》中&#xff0c;我们详细介绍了如何对Jenkins进行基本配置&#xff0c;包括系统设置、安全配置、插件管理以及创建第一个Job。通过这些配置&#xff0c;您的Jenkins环境已经具备了基本的功能和…

Qt文件下载工具

在Qt中实现文件下载功能&#xff0c;通常可以通过多种方式来完成&#xff0c;包括使用 QNetworkAccessManager 和 QNetworkReply 类&#xff0c;或者使用更高级别的 QHttpMultiPart 类。以下是两种常见的实现方法&#xff1a; 方法1&#xff1a;使用 QNetworkAccessManager 和…

AI操作系统势头正猛,以后LINUX,和window,Android,IOS等等的OS都将被AI OS所取代!

AI操作系统是一种旨在利用人工智能技术来优化和管理计算资源的操作系统。它不仅仅是一个传统意义上的操作系统&#xff0c;而是一个能够自主学习和适应用户需求的智能平台。以下是对AI操作系统的一些关键特点和它是否能取代现有操作系统的讨论&#xff1a; AI操作系统的关键特…

OpenCV图像处理——判断轮廓是否在圆环内

要判断一个轮廓是否在圆环内&#xff0c;可以将问题分解为两个步骤&#xff1a; 确保轮廓的所有点都在外圆内。确保轮廓的所有点都在内圆外。 下面是一个完整的示例代码&#xff0c;展示如何实现这一点&#xff1a; #include <opencv2/opencv.hpp> #include <iostr…

QT VTK 简单测试工程

目录 1 目录结构 2 文件源码 3 运行结果 4 报错及处理 使用编译好的VTK库进行测试 1 目录结构 2 文件源码 Pro文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. #…

Iceberg概念和特性

1. 快照 Iceberg会随着时间的推进,跟踪表生命周期中的所有数据集变化,并使用快照(Snapshots)来表示每一次变化后的数据集合,每一次数据操作的事务提交均会产生一个快照,并将其记录在元数据文件(Metadata)中。 基于快照的概念,Iceberg有以下特性: 事务性:写入快照成…

数据链路层协议 ------------- 以太网协议

文章目录 链路层解决的问题![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ab01312d49ee479082a2255ad9fbfc99.png)以太网协议认识以太网以太网帧格式认识MAC地址对比理解MAC地址和IP地址认识MTUMUT对IP协议的影响MTU对UDP协议的影响MTU对TCP协议的影响ARP协议ARP协议…

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(九)-无人机服务区分离

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…

从课本上面开始学习的51单片机究竟有什么特点,在现在的市场上还有应用吗?

引言 51单片机&#xff0c;作为一种经典的微控制器&#xff0c;被广泛应用于各种嵌入式系统中。尽管如今ARM架构的高性能低成本单片机在市场上占据主导地位&#xff0c;但51单片机凭借其独特的优势依然在某些领域保持着应用价值。本文将深入探讨51单片机的特点、架构、应用以及…

读人工智能全传13人工智能导致的问题2

1. 机器人sha手 1.1. 自主57的话题总是带有强烈的煽动性&#xff0c;许多人会本能地厌恶它&#xff0c;认为这样的系统是不道德的&#xff0c;永远不该被建立 1.2. 自主57的讨论大多源于战争中使用得越来越频繁的无人机 1.3. 无人机 1.3.1. 人驾驶的飞机&#xff0c;在菌用…

MySQL空间索引

空间类型是建立在空间类型字段上的。 空间类型 MySQL的空间类型很多&#xff0c;我就不逐一介绍了。重要分四大类&#xff1a; GeometryCurveSurfaceGeometryCollection 前三种&#xff0c;地理、曲线、曲面都是不可实例化的。Geometry有一个子类Point, Curve有一个直接子类L…

ceph 部署

端口号 NFS 2049 rpcbind 111 NFS 目录越深&#xff0c;写入性能越差 操作简单&#xff0c; 一.前言&#xff1a;存储知识 1、存储基础 单机存储设备 【1】DAS&#xff08;直接附加存储&#xff0c;是直接接到计算机的主板总线上去的存储&#xff09; IDE、SATA、SCSI、SAS…