javascript基础十:说说你对Javascript中this对象的理解

news2024/9/29 21:19:01

在这里插入图片描述
一、定义
函数的 this 关键字在 JavaScript 中的表现略有不同,此外,在严格模式和非严格模式之间也会有一些差别

在绝大多数情况下,函数的调用方式决定了 this 的值(运行时绑定)

this 关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象

举个粟子:

function baz() {
    // 当前调用栈是:baz
    // 因此,当前调用位置是全局作用域
    
    console.log( "baz" );
    bar(); // <-- bar的调用位置
}

function bar() {
    // 当前调用栈是:baz --> bar
    // 因此,当前调用位置在baz中
    
    console.log( "bar" );
    foo(); // <-- foo的调用位置
}

function foo() {
    // 当前调用栈是:baz --> bar --> foo
    // 因此,当前调用位置在bar中
    
    console.log( "foo" );
}

baz(); // <-- baz的调用位置

同时,this在函数执行过程中,this一旦被确定了,就不可以再更改

var a = 10;
var obj = {
  a: 20
}

function fn() {
  this = obj; // 修改this,运行后会报错
  console.log(this.a);
}

fn();

二、绑定规则

根据不同的使用场合,this有不同的值,主要分为下面几种情况:

  • 默认绑定
  • 隐式绑定
  • new绑定
  • 显示绑定

默认绑定
全局环境中定义person函数,内部使用this关键字

var name = 'Jenny';
function person() {
    return this.name;
}
console.log(person());  //Jenny

上述代码输出Jenny,原因是调用函数的对象在游览器中位window,因此this指向window,所以输出Jenny

注意:
严格模式下,不能将全局对象用于默认绑定,this会绑定到undefined,只有函数运行在非严格模式下,默认绑定才能绑定到全局对象

隐式绑定

函数还可以作为某个对象的方法调用,这时this就指这个上级对象

function test() {
  console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1

这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象

var o = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a); //undefined
        }
    }
}
o.b.fn();

上述代码中,this的上一级对象为b,b内部并没有a变量的定义,所以输出undefined

这里再举一种特殊情况


var o = {
    a:10,
    b:{
        a:12,
        fn:function(){
            console.log(this.a); //undefined
            console.log(this); //window
        }
    }
}
var j = o.b.fn;
j();

此时this指向的是window,这里的大家需要记住,this永远指向的是最后调用它的对象,虽然fn是对象b的方法,但是fn赋值给j时候并没有执行,所以最终指向window

new绑定
通过构建函数new关键字生成一个实例对象,此时this指向这个实例对象

function test() {
 this.x = 1;
}

var obj = new test();
obj.x // 1

上述代码之所以能过输出1,是因为new关键字改变了this的指向

这里再列举一些特殊情况:
new过程遇到return一个对象,此时this指向为返回的对象

function fn()  
{  
    this.user = 'xxx';  
    return {};  
}
var a = new fn();  
console.log(a.user); //undefined

如果返回一个简单类型的时候,则this指向实例对象

function fn()  
{  
    this.user = 'xxx';  
    return 1;
}
var a = new fn;  
console.log(a.user); //xxx

注意的是null虽然也是对象,但是此时new仍然指向实例对象

function fn()  
{  
    this.user = 'xxx';  
    return null;
}
var a = new fn;  
console.log(a.user); //xxx

显示修改
apply()、call()、bind()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数

var x = 0;
function test() {
 console.log(this.x);
}

var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply(obj) // 1

关于apply、call、bind三者的区别,我们后面再详细说

三、箭头函数

在 ES6 的语法中还提供了箭头函语法,让我们在代码书写时就能确定 this 的指向(编译时绑定)

举个粟子:

const obj = {
  sayThis: () => {
    console.log(this);
  }
};

obj.sayThis(); // window 因为 JavaScript 没有块作用域,所以在定义 sayThis 的时候,里面的 this 就绑到 window 上去了
const globalSay = obj.sayThis;
globalSay(); // window 浏览器中的 global 对象

虽然箭头函数的this能够在编译的时候就确定了this的指向,但也需要注意一些潜在的坑

绑定事件监听

箭头函数的this指向是 父级程序的this指向
如果没有父级程序 或者 父级程序没有this ,箭头函数的this指向是 window

const button = document.getElementById('mngb');
button.addEventListener('click', ()=> {
    console.log(this === window) // true
    this.innerHTML = 'clicked button'
})

上述可以看到,我们其实是想要this为点击的button,但此时this指向了window

包括在原型上添加方法时候,此时this指向window

Cat.prototype.sayName = () => {
    console.log(this === window) //true
    return this.name
}
const cat = new Cat('mm');
cat.sayName()

同样的,箭头函数不能作为构建函数

四、优先级

隐式绑定 VS 显式绑定

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

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

obj1.foo(); // 2
obj2.foo(); // 3

obj1.foo.call( obj2 ); // 3
obj2.foo.call( obj1 ); // 2

显然,显示绑定的优先级更高

new绑定 VS 隐式绑定

function foo(something) {
    this.a = something;
}

var obj1 = {
    foo: foo
};

var obj2 = {};

obj1.foo( 2 );
console.log( obj1.a ); // 2

obj1.foo.call( obj2, 3 );
console.log( obj2.a ); // 3

var bar = new obj1.foo( 4 );
console.log( obj1.a ); // 2
console.log( bar.a ); // 4

可以看到,new绑定的优先级>隐式绑定

new绑定 VS 显式绑定

因为new和apply、call无法一起使用,但硬绑定也是显式绑定的一种,可以替换测试

function foo(something) {
    this.a = something;
}

var obj1 = {};

var bar = foo.bind( obj1 );
bar( 2 );
console.log( obj1.a ); // 2

var baz = new bar( 3 );
console.log( obj1.a ); // 2
console.log( baz.a ); // 3

bar被绑定到obj1上,但是new bar(3) 并没有像我们预计的那样把obj1.a修改为3。但是,new修改了绑定调用bar()中的this

我们可认为new绑定优先级>显式绑定

综上,new绑定优先级 > 显示绑定优先级 > 隐式绑定优先级 > 默认绑定优先级

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

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

相关文章

进程控制与进程调度 —— 时间片轮转调度算法(C++版)

目录 实验一 进程控制与进程调度 一、实验目的 二、实验内容 三、数据结构及符号说明 四、运行环境说明 五、代码段 六、 效果展示 实验一 进程控制与进程调度 备注&#xff1a;大二&#xff08;下&#xff09;操作系统实验一 一、实验目的 掌握进程状态的转变、…

多次调用java.awt.Toolkit.getDefaultToolkit方法获得是同一个单例的Toolkit

多次调用java.awt.Toolkit.getDefaultToolkit方法获得是同一个单例的Toolkit java.awt.Toolkit.getDefaultToolkit()import java.awt.Toolkit;public class 多次调用Toolkit的getDefaultToolkit方法获得是同一个单例的Toolkit {static public void main (String...arguments)t…

WMS:系统窗口添加过程

WMS:系统窗口添加过程 1、经常使用的两大类窗口2、系统窗口StatusBar2.1 StatusBarWindowView添加流程2.2 简要时序图 android12-release 1、经常使用的两大类窗口 Android中的“窗口”类型有很多&#xff0c;经常使用的“窗口”大致分为两大类&#xff1a;一是&#xff0c;由系…

对于后端Linux的入门知识

为什么使用Linux 文章来自https://librehunt.org/&#xff0c;在这个网站里&#xff0c;你可以根据它提供的选项&#xff0c;最终选出适合你的Linux版本 It’s safe and private. No tracking. No company watching over you, no “big brother is watching you” nonsense. Ju…

article-三自由度机械臂运动学分析+仿真

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rOmeEm3I-1685366971102)(data:image/svgxml;utf8, )] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kCu0JrBB-1685366971103)(data:image/svgxml;utf8, )] 建立坐标系 1…

ROS:创建工作空间和编译功能包

目录 一、工作空间二、创建工作空间三、编译空代码的工作空间四、功能包五、创建功能包六、设置和检查环境变量七、功能包中的两个重要文件 一、工作空间 存放工程开发相关文件的文件夹。类似一个IDE&#xff08;例如Pycharm&#xff09;新建一个工程&#xff0c;就是一个工作…

权威认可!腾讯云EdgeOne入选Gartner® DDoS缓解方案市场指南

近日&#xff0c;Gartner发布《Market Guide for DDoS Mitigation Solutions》报告&#xff0c;腾讯云EdgeOne入选Gartner DDoS缓解方案市场指南。 “分布式拒绝服务&#xff08;DDoS&#xff09;缓解市场包括检测和缓解DDoS攻击并将其作为专用产品提供的供应商。它包括专业供…

有这个证书,网络安全工程师找工作不用愁

想要成为网络安全工程师&#xff0c;满足企业的用人要求。最基本的&#xff0c;你需要熟悉TCP/IP协议&#xff0c;熟悉sql注入原理和手工检测、熟悉内存缓冲区溢出原理和防范措施、熟悉信息存储和传输安全、熟悉数据包结构、熟悉Ddos攻击类型和原理。并且有一定的ddos攻防经验&…

I2C通信协议MPU6050

目录 I2C通信协议 硬件 软件 I2C时序 MPU6050 I2C通信协议 硬件 为了避免总线没协调好导致电源短路&#xff0c;配置为开漏输出&#xff0c;所有设备输出低电平不输出高电平&#xff0c;即右图。又为了避免高电平造成的引浮空&#xff0c;&#xff08;第三点&#xff09;总…

kotlin用CoroutineScope启动协程async等待结果返回

kotlin用CoroutineScope启动协程async等待结果返回 例如&#xff1a; import kotlinx.coroutines.*object MyCoroutineScope {private val coroutineContext Job() Dispatchers.Default CoroutineName("my_context")val coroutineScope CoroutineScope(corouti…

【Redis】聊一下Redis数据同步/复制

在分布式系统中&#xff0c;基本上所有的存储中间件都支持数据同步/复制功能&#xff0c;主要的原因是为实现高可用&#xff0c;单点宕机的故障&#xff0c;必须需要将数据进行共享&#xff0c;而共享的话&#xff0c;就需要将数据进行复制&#xff0c;对于已经学过的MySQL和Ka…

Jdk17中文在线手册(建议收藏)

本身学习技术就比较难&#xff0c;再来一个英文版的API&#xff0c;就难上加难&#xff0c;经过几周的研究翻译&#xff0c;JDK17最新版中文在线手册搞定&#xff0c;不要看错了哈是JDK17不是JDK1.7&#xff0c;全网最新的只有JDK11&#xff0c;JDK17中文在线手册是第一次出现&…

JavaEE进阶(5/29)SpringMVC

目录 1.复习 2.URL传参PathVariable 3.上传文件RequestPart 4.获取Cookie/Session/header 5.传统/维新获取cookies 6.传统/维信获得Header 7.获取Session&#xff08;非常重要&#xff09; 8.不加ResponseBody 9.如何获取Json数据&#xff0c;RequestBody 10.想…

王者之力,驭见未来 | 圣戈班量子膜全国核心店面大会圆满落幕!

5月24日&#xff0c;“王者之力&#xff0c;驭见未来”——2023年圣戈班量子膜全国核心店面大会在成都缇沃丽酒店隆重召开&#xff01; 圣戈班舒热佳特殊镀膜有限公司全球总裁Mehrotra Vishal先生、圣戈班舒热佳特殊镀膜有限公司亚太总裁陈剑超先生、圣戈班舒热佳特殊镀膜有限公…

opencv_c++学习(二十九)

一、监督学习的聚类方法 K近邻的方法&#xff1a; 首先给出一个阈值k&#xff0c;后寻找距离黑色圆点最近的k个元素&#xff0c;占据比例大的元素即为黑色所属的类别。如图所示&#xff0c;即k3时&#xff0c;黑色圆属于三角形&#xff0c;k5时圆点属于正方形。 支持向量机方…

设计模式-享元模式

问题背景 有一个小型的外包项目&#xff0c;就是给客户A做一个展示的网站&#xff0c;例如展示&#xff1a;这个网站展示的都是客户A的产品。然后可以A的朋友觉得不错&#xff0c;也希望做这样一个网站&#xff0c;但是要求有些不同&#xff0c;要求以新闻的形式展示。还有更多…

DORIS----漏斗转化分析案例实现

综合案例之漏斗转化分析 业务目标、到达路径&#xff0c;路径步骤、步骤人数&#xff0c;步骤之间的相对转换率和绝对转换率 每一种业务都有他的核心任务和流程&#xff0c;而流程的每一个步骤&#xff0c;都可能有用户流失。 所以如果把每一个步骤及其对应的数据&#xff08;…

【Linux】深入了解冯诺依曼体系结构与操作系统

目录 导读 &#x1f31e;专栏导读 &#x1f31e;冯诺依曼 &#x1f31e;冯诺依曼体系结构 &#x1f31b;木桶效应 &#x1f31e;操作系统(Operator System) &#x1f31b;概念 &#x1f31b;设计OS的目的 &#x1f31b;系统调用和库函数概念 导读 六一儿童节快到了&…

Envoy 物联网模块开发---串口服务器 (一)

一、背景 最近业余时间想基于Envoy 开发一个串口网关&#xff0c;主要是想把一些 modbus、bacnet 以及 mqtt 等物联网协议接入Envoy中&#xff0c;当读到串口数据后可以转发成对应的网络协议 二、Envoy的优势 选择Envoy的话主要是因为Envoy的代码已经十分健全了&#xff0c;零…

(数字图像处理MATLAB+Python)第九章图像形态学运算-第三节:二值图像的形态学处理

文章目录 一&#xff1a;形态滤波&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 二&#xff1a;图像的平滑处理&#xff08;1&#xff09;概述&#xff08;2&#xff09;程序 三&#xff1a;图像的边缘提取&#xff08;1&#xff09;概述&#xff08;2&#xff…