【JS进阶】this指向

立创开源:基于STM32F407的大疆M30T无人机PSDK机载开发板硬件设计与飞行控制实现 本文详细介绍了基于STM32F407微控制器为大疆M30T无人机设计PSDK机载开发板的完整流程。从关键的E-Port接口电路设计、电源保护,到STM32最小系统搭建,再到通过PSDK实现与无人机的通信及基础飞行控制,提供了从硬件到软件的全栈实战指南,助力开发者快速入门无人机负载开发。 阅读详情

详解JS中的this

1.关于this

1.1 为什么需要使用this?

this提供了一种更加优雅的方式来隐式“传递”一个对象引用,因此可以将 API 设计 得更加简洁并且易于复用。

this 使函数可以自动引用合适的上下文对象。

1.2 this是什么?

在学习 JS 的过程中,往往会产生这样的误解:this指向自身或函数的作用域。

但实际上:

this 既不指向函数自身也不指向函数的词法作用域;

this的指向,是在函数被调用的时候确定的,也就是执行上下文被创建时确定的;

this 的指向和函数声明的位置没有任何关系,只取决于函数的调用位置(也就是函数的调用方法);

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

2.this的解析

先来了解几个概念。

2.1 调用位置

调用位置就是函数在代码中被调用的位置(而不是声明的位置)。

寻找调用位置就是寻找“函数被调用的位置”,其中最重要的就是分析调用栈。(即为了到达当前执行位置所调用的所有函数)

而我们所需要的调用位置就在当前执行函数的前一个调用中。

调用栈又称为“执行栈”。调用栈主要用于记录代码执行位置、当前执行环境。

例如:

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 的调用位置
2.2 绑定规则
a.默认绑定

针对独立函数调用,同时也是无法应用其它绑定规则时的默认规则。

此时this指向全局对象window。

例如:

function foo() {
    console.log( this.a ); // this指向全局对象
}
var a = 2;
foo(); // 2

对于默认绑定来说,决定this绑定对象的并不是调用位置是否处于严格模式,而是调用位置的函数体是否处于严格模式。

如果函数体处于严格模式,this会被绑定到undefined,否则this会被绑定到全局对象。

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

var a = 2; 
(function(){  
    "use strict"; 
    foo(); // 2,严格模式下与 foo() 的调用位置无关
})();
b.隐式绑定

在一个函数上下文中,this由调用者提供,由调用函数的方式来决定。

如果调用的函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。

例如:

function foo() {
    console.log( this.a );
}
var obj = {
    a: 2,
    foo: foo
};
obj.foo(); // 2
// 调用位置会使用 obj 上下文来引用函数,
// 因此你可以说函数被调用时 obj 对象“拥有”或者“包含”它
// 所以此时的 this 指向调用 foo 函数的 obj 对象

对象属性引用链中,只有最顶层或者说最后一层会影响调用位置,也就是说this指向最终调用函数的对象。举例来说:

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

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

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

obj1.obj2.foo(); // 42,此时的 this 指向 obj2 对象

此时最终调用函数 foo() 的为 obj2,因此其中的this指向 obj2 对象。

c.隐式丢失
function foo() {
    console.log( this.a );
}

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

var bar = obj.foo; // 函数别名!函数的引用而不是函数的调用!!!
var a = "oops, global"; // a 是全局对象的属性
bar(); // "oops, global"

// 虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是foo 函数本身,
// 因此此时的 bar() 其实是一个不带任何修饰的函数调用,因此应用了默认绑定

…

d.显式绑定 —call()和apply()方法

call()和apply()方法,它们的第一个参数是一个对象,它们会把这个对象绑定到this,接着在调用函数时指定这个this。

function foo() {
    console.log( this.a );
}
var obj = {
    a:2
};
foo.call( obj ); // 2
// 在调用 foo 时强制把它的 this 绑定到 obj 上

后面的文章会对这两个方法做详细的解析,这里就不多说了。

e.new绑定

在JavaScript 中,构造函数只是一些使用new操作符时被调用的函数。它们并不会属于某个类,也不会实例化一个类。实际上,它们甚至都不能说是一种特殊的函数类型,它们只是被new操作符调用的普通函数而已。

那么**new操作符做了哪些操作呢?或者说发生构造函数调用**时,执行了哪些操作呢?

  1. 在内存中创建一个全新的对象,并为其链接原型;
  2. 将构造函数的作用域赋给新对象,因此,this就指向了这个新对象;
  3. 执行构造函数中的代码,为这个新对象添加属性、方法等;
  4. 若函数没有返回其它对象,那么new表达式中的函数调用会自动返回这个新对象;(这也是为什么构造函数里面不需要return)

实际上,我们可以模拟一下这个过程:

function mynew() {
    // 1. 新建⼀个实例对象
    let obj = {};
    // 2. 获得构造函数
    let con = [].shift.call(arguments);
    // 3. 链接原型
    obj.__proto__ = con.prototype;
    // 4. 绑定this,执⾏构造函数
    let res = con.apply(obj,arguments)
    // 5. 返回新对象
    return typeof res === 'object'? res : obj;
}

下面是一个实例:

function foo(a) {
    this.a = a;
}
var bar = new foo(2);
console.log( bar.a ); // 2
// 使用new 来调用foo(..)时,我们会构造一个新对象并把它绑定到foo(..)调用中的this上

了解了 new ⼀个实例对象的过程后,我们发现在普通函数作为构造函数时,其内会改变 this 指向以及修改原型,⽽箭头函数⽆法改变this指向以及没有原型,所以不能作为构造函数使⽤!

2.3 判断this

this指向的判断可以按照下面的优先级顺序来判断函数在某个调用位置应用的是那条规则:

  1. 函数是否在new中调用?— new绑定

    如果是,则此时**this绑定的是最新创建的对象**。

    例如:

    var bar = new foo();
    
  2. 函数是否通过call、apply进行显式绑定,或者硬绑定调用?— 显式绑定

    如果是,则此时**this绑定的是指定的对象**。

    例如:

    var bar = foo.call(obj2);
    
  3. 函数是否在某个上下文对象中调用?— 隐式绑定

    如果是的话,this绑定的是那个上下文对象。

    例如:

    var bar = obj1.foo();
    
  4. 如果都不是的话,使用默认绑定。

    如果在严格模式下,就绑定到undefined,否则绑定到全局对象。

2.4 绑定的例外情况
  1. 被忽略的this

    null 或者undefined作为this的绑定对象传入call、apply或者bind,这些值在调用时会被忽略,实际应用的是默认绑定规则。

    例如:

    function foo() {  
        console.log( this.a ); 
    } 
    
    var a = 2; 
    foo.call( null ); // 2
    
  2. 间接引用

    间接引用最容易在赋值时发生;间接引用时,调用这个函数会应用默认绑定规则。

    例如:

    function foo() {
        console.log( this.a );
    }
    var a = 2;
    var o = { a: 3, foo: foo };
    var p = { a: 4 };
    o.foo(); // 3
    (p.foo = o.foo)(); // 2
    

    赋值表达式p.foo=o.foo的返回值是目标函数的引用,也就是 foo 函数的引用。

    因此调用位置是 foo() 而不是 p.foo() 或者 o.foo()。

2.5 箭头函数的this

箭头函数并不是使用function关键字定义的,而是使用被称为“胖箭头”的操作符 => 定 义的。

箭头函数不使用 this的四种标准规则,而是根据外层(函数或者全局)作用域来决定 this。

function foo() { 
    // 返回一个箭头函数  
    return (a) => { 
        //this 继承自 foo() 
        console.log( this.a );  
    }; 
} 
var obj1 = {  
    a:2 
}; 
var obj2 = {  
    a:3 
};

var bar = foo.call( obj1 ); 
bar.call( obj2 ); // 2, 不是 3 !

// foo() 内部创建的箭头函数会捕获调用时 foo() 的 this。
// 由于 foo() 的 this 绑定到 obj1, bar(引用箭头函数)的 this 也会绑定到 obj1,

注意,this一旦被确定,就不可更改,所以箭头函数的绑定无法被修改。(new 也不行!)

总结

如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断 this 的绑定对象。

  1. 由 new 调用?绑定到新创建的对象。
  2. 由 call 或者 apply(或者 bind)调用?绑定到指定的对象。
  3. 由上下文对象调用?绑定到那个上下文对象。
  4. 默认:在严格模式下绑定到 undefined,否则绑定到全局对象。

可以用一张图来总结:
在这里插入图片描述
ES6 中的箭头函数并不会使用四条标准的绑定规则,而是根据当前的词法作用域来决定 this,具体来说,箭头函数会继承外层函数调用的 this 绑定(无论 this 绑定到什么)。这其实和 ES6 之前代码中的 self = this 机制一样。

使用 syncstart 实现同场景下多个音视频音轨自动化同步 如果需要在视频编辑中同步多个机位的音轨,使得相同的视频能够同时播放,手动操作可能会变得相当复杂。特别是当处理多个视频文件时,例如有10个视频需要互相匹配,实现一对多的同步关系,这就涉及到为每对视频生成匹配的音轨数据。手动完成这样的任务,如生成90套对应的音轨数据,不仅耗时而且容易出错。因此,使用脚本自动化这一过程是一个更为高效和准确的解决方案。通过编写脚本,您可以批量处理多个视频文件,自动同步它们的音轨,大大简化了音视频编辑的工作流程,并确保了同步的准确性。 阅读详情

相关推荐

机器人示教器方案昆仑通态脚本实现( 三菱FX3U+昆仑通态3轴联动))

项目应用场景:最终客户需要自由的修改程序流程,如检测什么信号,多少时间,再进入下一步,轴定位轨迹可以自由修改,方便最终可以在不修改PLC程序的情况下,自由示教程序。3.指令数量可以自行添加,在内存足够的情况下,无限制,只需要在PLC框架里面写好每个指令执行的内容就可以了,不需要在程序里面重复写相同类容;4.模板有延时指令,输入指令,输出指令,伺服定位指令,焊钳控制指令,自动修磨指令,转矩模式指令,结束指令等(可自行添加);1.有类似示教器编程功能,可以任意位置插入指令,可以任意位置删除指令;

huanyuecuiyu的博客 969

JavaScript中的this详解

JavaScript中的this详解 this一直都是难点所在,我查阅资料,对this进行了一些用法和误解的举例与分析,也帮助自己学习和理解。 目录 默认绑定 隐式绑定 显式绑定 new绑定 一些特殊例子 默认绑定 var a = 2; function foo(){ console.log(this.a); } foo();//2 这是一个this最简单的例子...

AHRL__的博客 532

PTA 编程题(C语言)-- 然后是几点

PTA 编程题(C语言)-- 然后是几点

LCCprogrammer 5074

JavaScript中this关键词和var、let、const之间的关系

一、this关键词 this是什么?this关键词指的是它所属的对象 它的值取决于它的使用位置: 1.在方法中的this,this指的是该方法的“拥有者”。如下实例,person对象是message方法的拥有者。 var person = { id : 1, name: "bill", age: 20 message : function (){ return this.name + ...

qq_42248962的博客 294

【ROS2实体机械臂驱动】封装珞石ROS2驱动库ros2_rokae_driver_lib

这一篇文章将封装为,和之前一篇文章《ROS2 编译、打包、封装三方库(Knet为例)_ros插件编译成静态库-优快云博客》写的封装,区别在于优化了cmake dependencies和include等属性和宏定义,同时对于多库内部依赖的情况做了特定处理,更加方便外部调用。其中珞石的编译参考博主之前的文章rokae xCoreSDK C++测试使用,这里不再做赘述。通过这篇文章对于如何打包机械臂厂家提供的三方库做了进一步说明,方便用于不同机械臂厂家的三方库封装调用。!!

机器人梦想家 Bing Lee 1398

利用pytorch长短期记忆网络LSTM实现股票预测分析

长短时记忆网络(Long Short Term Memory Network, LSTM),是一种改进之后的循环神经网络,可以解决RNN无法处理长距离的依赖的问题,目前比较流行。LSTM主要就是加入了三个门控:第一个开关遗忘门:负责控制继续保存长期状态c;第二个开关输入门:负责控制把即时状态输入到长期状态c;第三个开关输出门:负责控制是否把长期状态c作为当前的LSTM的输出。

优快云 精品推荐 1万+

var that =this的用法详解

在小程序开发中,var that =this的声明很常见。举个例子,代码如下! 示例代码1 //index.js Page({ data: { toastHidden: true, }, loadData: function () { var that = this//这里声明了that;将this存在that里面 wx.request(...

qq_32534441的博客 8682

复旦微FMSH_Procise安装流程

双击FMSH_Procise_2021.1_full_win64_202103151947.exe 选择好安装目录后点击“Next” 一路next 点install 找技术支持代为申请 License,将电脑MAC地址发过去,将获得的 license 拷贝到 procise 安装目录“data”文件夹,即可使用 procise。点license manager和copy license 将licence,.lic文件放到这个目录 要是报下面错误要...

wangjie36的博客 1万+

如何使用JavaScript里面的this

关于this可能是刚刚学习JavaScript学生党的一大问题 var r=1; function user(){ console.log(this.r);//在函数调用里默认为window } var r={ s:2, q:function(){ console.log(this.s) }, r:function(){ (function(){ console.log(this.sa)//作为匿...

AI模型自研小参数,智能体开发,langchain,langgraph,垂直类模型开发,魔搭社区模型微调,人工智能软件全周期落地,从0到1开发小模型,多模态,多模型,多智能体,然后数据中台,模型中台,集群部署算力调度,并发优化模型 173

从 Material Requirements Planning 看 SAP 物料计划的底层控制逻辑

文章摘要:SAP中的MRP(物料需求计划)不仅仅是运行一个程序(如MD01N),其关键在于主数据和组织层级的正确配置。MRP的核心是解决"何时需要多少物料"的问题,涉及采购、生产、库存等多种供应来源。物料主数据的MRP视图必须在组织层级(如工厂、存储位置)下维护,不同层级的计划逻辑可能完全不同。S/4HANA更强调MRP Area作为细分计划单位,取代传统存储位置MRP。实施时需注意MRP Profile的合理使用,避免批量错误,并特别关注物料生命周期管理(如停用物料和替代件),这些因素共同决定了MRP能否

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1412

ABAP CDS 和 HANA SQL 的关系

摘要: ABAP CDS与HANA SQL既有紧密联系又有本质区别。ABAP CDS作为语义数据建模框架,在SQL基础上扩展了业务语义层,通过注解(annotations)、关联关系(associations)等机制为数据附加业务含义,并支持权限控制、客户端处理等ABAP平台特性。虽然CDS实体最终会转换为HANA数据库对象执行,但它并非简单的SQL封装,而是构建了独立于数据库的语义模型。二者在数据库执行层深度融合,ABAP CDS通过代码下推技术将计算任务优化到HANA层完成。实际开发中应优先使用ABAP

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 858

用 JavaScript 操作字符串

 虽然 JavaScript 有很多用处,但是处理字符串是其中最流行的一个。下面让我们深入地分析一下使用 JavaScript 操作字符串。在 JavaScript 中, String 是对象。 String 对象并不是以字符数组的方式存储的,所以我们必须使用内建函数来操纵它们的值。这些内建函数提供了不同的方法来访问字符串变量的内容。下面我们详细看一下这些函数。   操作字符串的值

星光熠熠 的专栏 754

VR大空间开发前期,设备选项与流程

欢迎开发者加入 VR 大空间开发之旅!本系列教程将以 Pico 和 HTC 设备为核心,系统拆解从基础搭建到功能实现的全流程,助你快速掌握开发要点。本系列共 12 篇,专为有编程基础但缺乏大空间开发经验的开发者设计。前 7 篇针对 Pico 和 HTC 设备差异分别讲解,后续步骤通用。核心目录如下:​1. 空间环境要求 - 灯光设置 - 场地面积规划 - 识别图案设计2. 网络部署方案3. 客户端体验模式解析 - 一体机模式 - 云渲染模式 - 背包体验模式4. Pico空间录制方法

unitygroup的博客 1352

JavaScript进阶:js的一些学习笔记-this指向,call,apply,bind,防抖,节流

this指向,call,apply,bind,防抖,节流

坚持不懈的大白的博客 1120

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

JavaScript进阶之this指向

this指向最常听到的一句话就是:它始终指向调用它的对象,然而却忽略了this所在的环境 再谈上下文 在上下文的章节我们说到,在这个阶段,执行上下文会分别创建变量对象、确定作用域链,以及this指向 在变量对象章节我们讲到,在函数调用栈中,如果当前执行上下文处于函数调用栈的栈顶,则意味着当前上下文处于激活状态,并且上下文处于执行阶段,此时的变量对象称之为活动对象(AO)。活动对象中包含...

高先生的猫 528

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【JavaScript 进阶教程】函数的定义 调用 及 this指向问题

这篇文章开始我们函数的进阶篇,和我们JavaScript基础学的函数有了很多拓展,这篇文章首先我们从函数的定义,调用,及其 this指向 来一个总结。通过刚才的第三种函数的声明方法,是个构造函数,我们会想到什么,为什么函数也有构造函数,难道函数也是对象吗?函数内部的 this 指向谁,是由我们调用时才知道的,一般情况是指向函数的调用者,下面是上一板块出现的几类函数的this指向。立即执行函数通常用于匿名函数的调用,立即执行函数是自动调用的。匿名函数即没有名字的函数,匿名函数的调用需要使用。...

weixin_52212950的博客 4353

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

JS进阶之this指向

1. this指向汇总 this指向:指向其调用者 简单函数 function f(){ console.log(this) //window }; f(); //因为代码不是运行在严格模式下,this又必须是一个对象,所以他的默认值为全局对象window //严格模式下为undefined 内置函数 this ==== window setTimeout(f,1000); //window 回调函数 ——

weixin_45457352的博客 195

Js进阶1-this指向问题

this 指向问题详解

晴雪月乔的博客 143

JavaScript进阶讲解四—>this的指向二

本节我们继续讲js中this的绑定问题 一、系统API中的this setTimeout(function() { console.log(this); // window }, 100); [1,2].forEach(function(item) { console.log(this); // window }); [1,2].forEach(function(item) { console.log(this); // a }, 'a'); [1,2].map(function(

wangyuiba1314的博客 371

JavaScript进阶讲解三—>this的指向一

上一节我们讲了闭包的原理及形成,希望大家可以多去理解一下。本节我们开始讲js中this的指向问题 一、结论与规则与优先级排序 结论 函数在调用时,JavaScript会默认给this绑定一个值。 this的绑定和定义的位置(编写的位置)没有关系。 this的绑定和调用方式以及调用的位置有关系。 this是在运行时被绑定的。 规则 默认绑定。 隐式绑定。 显示绑定。 new绑定。 优先级排序 .隐式绑定高于默认绑定(默认绑定最低) 显示绑定优先级高于隐式绑定 new绑定优先级高于隐式绑定 new绑

wangyuiba1314的博客 234

函数中this的指向问题 ——Javascript 进阶知识整理

闭包中this的指向闭包中的函数,调用的对象是全局对象,所以闭包中this的指向是window,这就会带来一个问题,闭包函数如果想使用外部函数中与全局对象同名的变量,使用this.val是不行的,执行时,这回引用全局对象的变量,这个时候需要将外部对象的this在外部函数中暂存起来(比如var that=this),然后在闭包的内部函数中通过缓存的外部函数引用that找到外部函数的变量。 * 使用a

lqadam的博客 1517

【js进阶】这应该是最简单的 this 指向解析了!

文章目录   现在已经0202年了,大家大多都富裕,能够用上ES6新特新了,所以对于this的指向问题也没有ES5时期关注了;再者,一般的开发过程中对于函数或者作用域的层级也没有嵌套太深,所以也不常遇到因为this指向不明产生的错误。常在河边走哪能不沾水,接触的项目多了,难免会遇到一些老代码,最好能够了解一下this的指向;再退一步说,面试中this指向可是避不开的点!但是,看到这篇文章只需要记住一句话就能解决所有this指向问题——this永远指向离它最近的调用对象! ...

goodloving的博客 274

【JavaScript高级进阶】初识类,函数进阶,如何改变this指向

class类的了解,如何使用对象,字符串和数组方法configurabletrue的特性

zhaochen1127的博客 1127

JavaScript中this指向哪儿?如何确定this?-前端面试进阶

看了前面两章节,我们大概能理解this是什么?它其实就是一个执行上下文中的一个属性,大家也可以简单的把this当作一个对象,只不过该对象指向哪儿是在函数调用的时候确定的。我们简单总结一下thisthis是在运行时绑定的,不是在编写时绑定this的绑定与函数的声明和位置没有任何关系函数在调用时,会创建一个执行上下文,this就是这个执行上下文中的一个属性,在函数执行的时候可以用到this。所以this是在函数调用的时候确定绑定关系的,也就是运行时。所以,this就是一个对象,this。

loveX001的博客 844

js进阶之三 this指向

本文不考虑严格模式(错误之处感谢提出,请勿喷) function 函数 this 指向一共有4种规则:默认绑定,隐式绑定,显式绑定, new绑定 默认绑定 function fn() { var a = 10; console.log(this.a); } var a = 1; fn(); // a: 1 fn在没有任何修饰的被调用,只能使用默认绑定;this指向了直...

木呆呆的博客 237

改变函数内部 this 指向丨JavaScript 函数进阶

都可以改变函数内部的this指向.

黑马程序员官方博客 183
上一篇: 【JS进阶】执行上下文与执行栈
下一篇: 【JS进阶】JS中的闭包
cannotbecounted
博客等级 码龄7年 101粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值