【JS】JavaScript 中 this 关键字

JavaScript 中 this 关键字

    • this 是什么
    • this 的绑定规则
    • this 的指向

this 是什么

this 是一个关键字,能够在函数执行过程中访问运行环境,它的值根据函数的调用方式和上下文而变化,所以 this 是动态的,动态指向当前函数的运行环境。

this 是一个对象,当函数执行时产生的内部对象,this 指向只与函数的执行环节有关,与函数的声明无关。

this 是一个指针型变量,在 JavaScript 中没有指针的概念,但是this真实地指向当前调用对象,能够在函数内部访问和操作当前对象的属性和方法。

this 的绑定规则

1、默认绑定:

当函数独立调用时,即没有任何上下文对象时,默认绑定规则会将 this 绑定到全局对象(在浏览器中是 window 对象,在 Node.js 中是 global 对象)。

在严格模式下,默认绑定会将 this 绑定为 undefined

function foo() {console.log(this);
}foo(); // 在浏览器中输出:window,在 Node.js 中输出:global
function foo(){console.log(this.a);
}var a=2;
foo(); //在浏览器中输出:2,在 Node.js 中输出:undefined

2、隐式绑定:

当函数作为对象的方法调用时,会将 this 绑定到调用该方法的对象上。

function foo(){console.log(this); // {name: 'zhangsan', sayHello: ƒ}console.log(this.name); // zhangsan
}var obj={name:'zhangsan',sayHello:foo //函数引用
}obj.sayHello()

下面方式是同样的:

const obj = {name: 'zhangsan',sayHello: function() {console.log('Hello, ' + this.name);}
};obj.sayHello(); // 输出:Hello, zhangsan

对象属性引用链只有在上一层或者说最后一层的在调用位置起作用,即只会指向上一个调用该函数的对象。

function foo(){console.log('指向的是:', this.name);}var obj1={name:'obj1',foo:foo //隐式绑定的函数
}var obj2={name:'obj2',obj1:obj1
}obj2.obj1.foo();//指向的是:obj1  绑定对象是obj1,而不是obj2

3、显示绑定

通过 callapplybind 方法,可以显式地指定函数内部的 this 值。

  • call 方法接受一个指定的对象作为第一个参数,将该对象绑定到函数的 this。如果不传参数或传null、undefined 参数时都指向 Windows。
    语法:function.call(thisArg, arg1, arg2, …) 其中,thisArg是要绑定的对象,它将代替调用函数中的this关键字。后面的参数arg1、arg2等是可选的参数,它们被传递给调用的函数。
function foo() {console.log('Hello, ' + this.name);
}var obj = {name: 'obj'
};// 将 obj 绑定到函数 foo 上面
foo.call(obj); // 输出:Hello, obj
  • apply 方法与 call 类似,参数以数组形式接受。
    语法:function.apply(thisArg, [argsArray])。其中,thisArg是要绑定的对象,argsArray是一个数组类型的参数列表,它们被传递给调用的函数。
function foo(params) {console.log(params + ', ' + this.name);
}var obj = {name: 'obj'
};// 将 obj 绑定到函数 foo 上面,并向 foo 传递参数
foo.apply(obj,['Hello']); // 输出:Hello, obj

call和apply方法在函数调用时立即执行,而bind方法返回一个新的函数,需要手动调用。apply的参数需要以数组形式传入。

  • bind 方法会创建一个新函数,并将指定的对象绑定到新函数的 thisbind 方法不会立即调用函数,而是返回一个绑定了 this 的新函数。
function foo() {console.log('Hello, ' + this.name);
}var obj = {name: 'obj'
};// bind 会创建一个绑定 this 的新函数进行返回,但不会立即调用
var newFoo = foo.bind(obj);
newFoo(); // 输出:Hello, Bob

4、new 绑定:当使用 new 关键字调用函数作为构造函数来创建新对象时,this 会绑定到新创建的对象。

function Person(name) {this.name = name;
}var zhangsan = new Person('Zhangsan');
console.log(zhangsan.name); // 输出:Zhangsan

5、箭头函数:箭头函数中的 this 继承自外部作用域,与函数的调用方式无关。

const obj = {name: 'Alice',sayHello: () => {console.log('Hello, ' + this.name);}
};obj.sayHello(); // 输出:Hello, undefined

this 的指向

1、函数的普通调用

当函数直接调用时,this 指向调用它的那个对象,一般使用默认绑定。

function foo() {let a = "function name";console.log('a', a); // function nameconsole.log('this.a', this.a); // window name
}var a = "window name";
foo();//调用A(),当前运行环境是window,this指向window对象

2、构造函数

构造函数的 this 永远指向实例化对象

严格模式下,如果构造函数不加new调用,this 指向的是 undefined 如果给他赋值,则会报错

var Func = function () {this.a = "我是构造函数的属性";this.fun = function () {console.log(this);}
}
let myFunc = new Func();
myFunc.fun();//Func { a: '我是构造函数的属性', fun: [Function (anonymous)] }

3、箭头函数

箭头函数不会创建自己的 this ,所以它没有自己的 this,它只会从自己的作用域链的上一层继承 this。

如果外部函数是普通函数,this 的指向取决于外部函数的绑定类型,外部函数!=定义箭头函数的外部对象。

function foo() {var a = "function"setInterval(() => {console.log(this.a);//浏览器每个1秒打印window; node.js每隔一秒打印undefined}, 1000)
}
var a = "window"
foo();//箭头函数外部函数是foo; foo没有任何绑定,则使用默认绑定

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

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

相关文章

Lazada全托管是什么?Lazada全托管ERP哪个好用?

做工厂及拥有自有品牌的你,是否因为跨境的头程费用、仓储费用、尾程费用如何结算而烦恼?是否因为不懂市场、不懂运营、不够专业而对跨境电商领域望而却步?那么,你或许可以尝试全托管。 一、什么是全托管 全托管是近两年电商领域…

Python之函数进阶-柯里化

Python之函数进阶-柯里化 柯里化是一种将多参数函数转化为单参数高阶函数的技术。 具体来说,柯里化过程会将一个接受多个参数的函数,转换成一系列接受一个参数的函数,这些函数在内部组合起来,最终完成原函数的运算。 柯里化是一…

【一】【设计模式】类关系UML图

1. 继承(Generalization) 继承是对象间的一种层次关系,允许子类继承并扩展父类的功能。 UML线:带有空心箭头的直线,箭头指向基类(父类)。 class Parent {public void parentMethod() {System.…

AIOps 智能运维:有没有比专家经验更优雅的错/慢调用分析工具?

作者:图杨 工程师小 A 刚刚接手他们公司最核心的电商系统的运维工作,小 A 发现,在生产环境中,系统明明运行得非常稳定,但是总会出现一些“诡异”的情况。比如: 偶尔会一些错误调用,但是&#…

Android UI:ViewTree中的事件传递

文章目录 ViewTree: 组合模式measure事件的传递 事件传递: View/ViewGroup的measure和onMeasureLinearLayout重写onMeasureRelativeLayout重写onMeasurelayout事件的传递 事件传递:View/ViewGroup的layout和onLayout LinearLayout重写onLayout RelativeLayout重写onLayoutdraw…

C语言--数据到字符串的相互转换:将数据转换为2进制,16进制,10进制,8进制 字符串类型;字符串转换为整型 常用的函数 与stdlib 库函数说明

数据 --> 字符串(2进制16进制10进制8进制) 包含&#xff1a;整型数据转换为 2进制字符串&#xff1b; 整型数据转换为16机制数据&#xff1b;整型数据转换为 10进制字符串&#xff1b; 1. 整型数据转换为 2 进制数据字符串&#xff1a; #include <stdio.h>// 将整…

python: inspect模块各函数的用法

python: inspect模块各函数的用法 inspect模块也被称为 检查现场对象。这里的重点在于“现场”二字&#xff0c;也就是当前运行的状态。 inspect模块提供了一些函数来了解现场对象&#xff0c;包括 模块、类、实例、函数和方法。 inspect函数主要用于以下四个方面 对是否是模…

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列&#xff1f;二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机&#xff08;Virtual Host&#xff09;3.2.2、交换机&#xff08;Exchange&#xff09;3.2.2…

shopee店铺降权了怎么办?shopee店铺降权恢复步骤

当您发现自己的Shopee店铺被降权时&#xff0c;这意味着您的产品在搜索结果中的排名下降&#xff0c;从而可能导致流量和销售额的减少。面对这种情况&#xff0c;您需要采取一系列措施来恢复或提升店铺的权重。以下是一些具体的步骤和拓展的原因分析&#xff1a;一&#xff1a;…

3、设计模式之工厂模式2(Factory)

一、什么是工厂模式 工厂模式属于创建型设计模式&#xff0c;它用于解耦对象的创建和使用。通常情况下&#xff0c;我们创建对象时需要使用new操作符&#xff0c;但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口&#xff0c;使得我们可以在不暴露…

【深度学习笔记】7_7 AdaDelta算法

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 7.7 AdaDelta算法 除了RMSProp算法以外&#xff0c;另一个常用优化算法AdaDelta算法也针对AdaGrad算法在迭代后期可能较难找到有用解的…

嵌入式驱动学习第三周——linux内核链表

前言 在 Linux 内核中使用最多的数据结构就是链表了&#xff0c;其中就包含了许多高级思想。 比如面向对象、类似C模板的实现、堆和栈的实现。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程&#xff0c;未来预计四个月将高强度更新本专栏&#xff0c;喜欢的可以关注本博…

C#无法给PLC写入数据原因分析

一、背景 1.1 概述 C#中无法给PLC写入数据的原因有很多&#xff0c;这里分享网络端口号被占用导致无法写入的确认方法 1.2 环境 ①使用三菱PLC ②C#通过网口与PLC进行通讯 二、现象 1.1 代码 通过HslCommunication连接PLC时&#xff0c;连接返回成功&#xff0c;写入返回失败 …

snakeflow的springboot项目

Gitee搜索“liuxz/snakerflow”&#xff0c;它是spring boot集成了一款国产工作流引擎snakerflow。 下面是安装步骤&#xff1a; 创建数据库snaker-web&#xff0c;字符集设置成utf8mb4和utf8mb4_generic。不然的话&#xff0c;中文插入不进去。 运行sql命令 CREATE TABLE …

Kotlin:泛型

点击查看泛型中文文档 点击查看泛型英文文档 简介 与 Java 类似&#xff0c;Kotlin 中的类也可以有类型参数&#xff1a; class Box<T>(t: T) {var value t }一般来说&#xff0c;要创建这样类的实例&#xff0c;我们需要提供类型参数&#xff1a; val box: Box<…

调试安卓 gles性能瓶颈

目录 下载Arm Performance Studio编译Unity Shader运行malios调试用处和限制 原文请见&#xff1a;参考地址 使用mali offline shader compiler分析shader的性能瓶颈。 下载Arm Performance Studio 下载地址 编译Unity Shader 通常选择GLES3x。 You might need to select G…

智能控制:物联网智能插座对接文档

介绍 一开始买的某米的插座&#xff0c;但是好像接口不开放&#xff0c;所以找到了这个插座&#xff0c;然后自己开发了下&#xff0c;用接口控制插座开关。wifi的连接方式&#xff0c;通电后一般几秒后就会连接上wifi&#xff0c;这个时候通过接口发送命令给他。 产品图片 通…

idea配置自定义注释模版和其他模板

项目场景&#xff1a; idea配置自定义模版 自定义注释模版其他模板&#xff0c;包括syso快捷键&#xff0c;swith快捷键等 自定义注释模版 1、File and Code Templates 第一种类创建完后头部自动生成注释模板 打开idea&#xff0c;选择 Settings--> Editor--> File a…

nvm安装不同版本的node

在项目开发过程中&#xff0c;不同项目依赖的node版本不同&#xff0c;但频繁的卸载和安装很麻烦&#xff0c;这篇文章介绍nvm安装过程 1.nvm安装 这个网上随便找一篇跟着安装即可 nvm安装教程 2.nvm安装不同版本的node 网上普遍的方式是&#xff1a; 找到nvm安装目录下的s…