牢牢记住 this 的 五种情况

简介: 在全局上下文中,严格默认 this 为 undefined,非严格模式下,this 为 window。块级作用域的 this 是继承所在上下文中的 this 。在函数的私有上下文中,this 情况多种多样。

网络异常,图片无法展示
|


前言


在全局上下文中,严格默认 this 为 undefined,非严格模式下,this 为 window。块级作用域的 this 是继承所在上下文中的 this 。在函数的私有上下文中,this 情况多种多样。

注意 this 并不是执行上下文,EC 是执行上下文,this 是执行主体。


1. 元素的事件


给元素的某个事件行为绑定方法,事件触发,方法执行,此时方法中的 this 一般都是当前元素本身。


// DOM0
 btn.onclick = function anonymous() {
    console.log(this); // this指向元素本省
 }
 // DOM2
 btn.addEventListener('click', function anonymous() {
     console.log(this); // this指向元素本省
 }, false);
 // DOM2-ie中
 btn.attachEvent('onclick', function anonymous() {  
    // <= IE8
     console.log(this); // this -> window 特殊情况
 })


2. 普通函数执行


普通函数执行,它里面的 this 取决于执行方法前面是否有“点”,有“点”,“点”前面是谁,this 就是谁,前面没有“点”,非严格模式 this 是 window,严格模式是 undefined。


3. 构造函数执行


构造函数执行,this 执行当前类的实例。


function Func() {
    this.name = "F";
    console.log(this); //=>构造函数体中的THIS在“构造函数执行”的模式下,是当前类的一个实例,并且THIS.XXX=XXX是给当前实例设置的私有属性
}
Func.prototype.getNum = function getNum() {
    // 而原型上的方法中的THIS不一定都是实例,主要看执行的时候,“点”前面的内容
    console.log(this);
};
let f = new Func;
f.getNum();
f.__proto__.getNum();
Func.prototype.getNum(); 


4. 箭头函数


箭头函数中没自身的this,所用的 this 都是上下文中的 this 。


  • 箭头函数没有this
  • 箭头函数没有prototype
  • 箭头函数没有constructor
  • 箭头函数不能被new执行
  • 箭头函数没有arguments,如果想用实参集合只能使用...args。


普通函数执行:


  • 形成私有上下文 (和AO)
  • 初始化作用域链
  • 初始化THIS
  • 初始化ARGUMENTS
  • 形参赋值
  • 变量提升
  • 代码执行


箭头函数执行:

  • 形成私有上下文 (和AO)
  • 形参赋值
  • 代码执行
  • 代码执行的时候遇到 this 直接找上级上下文中的 this。


let obj = {
    i: 0,
    // func:function(){}
    func() {
        // THIS:OBJ
        let _this = this;
        setTimeout(function () {
            // THIS:WINDOW 回调函数中的THIS一般都是WINDOW(但是有特殊情况)
            _this.i++;
            console.log(_this);
        }, 1000);
    }
};
obj.func();


5. call/apply/bind


call/apply

- 第一个参数就是改变 this 的指向,写谁就是谁,在非严格模式下,null/undefined 指向的是 window。
- call/apply 的唯一区别就是,传递参数不一样,apply 第二个参数是数组,call的参数是一个一个传递。
- call 的性能要比 apply 好一些(尤其是传递给函数的参数超过三个的时候)

bind

-  call/apply都是改变this的同时就把函数执行了,但是bind不是立即执行函数,属于预先改变this和传递一些内容,利用的是柯理化的思想。

这里提到这个 call/apply/bind 在面试中也常也会被问到关于如何自己实现这三个方法,其实不难,只要理解这三个方法就可以手写他们了。


apply源码-手写apply源码


~(function(proto){
  function apply(content, args) {
    if (content === undefined || contetn === null) {
      content = window;
    } else {
      content = Object(content);
    }
    content.$fn = this;
    var res = content.$fn(...args);
    delete content.$fn;
    return res;
  }
  proto.apply = apply;
})(Function.prototype)


call源码-手写call源码


~(function(proto){
  function call(content, args) {
    if (content === undefined || contetn === null) {
      content = window;
    } else {
      content = Object(content);
    }
    content.$fn = this;
    var res = content.$fn(...args);
    delete content.$fn;
    return res;
  }
  proto.call = call;
})(Function.prototype)


bind源码-手写bind源码


~(function(proto) {
    function bind(content) {
        if(content === undefined || content === null) {
            content = window;
        }
        // 获取实参集合
        var args = [].slice.call(arguments, 1);
        // 最后要执行的函数
        var _this = this;
        return function anonymous() {
            var amArgs = [].slice.call(arguments, 0);
            _this.apply(content, args.concat(amArgs));
        }
    }
    proto.bind = bind;
})(Function.prototype);
~(function(proto) {
    function bind(content = window, ...args) {
        if (content === null) {
            content = window;
        }
        return (...amArgs) => {
            // 经测试apply的性能在三个参数以上是没有call好的
            this.call(content, ...args.content(amArgs));
        }
    }
    proto.bind = bind;
})(Function.prototype);
目录
相关文章
|
3月前
|
数据采集 人工智能 自然语言处理
从零开始学AI:Python完整操作教程
本教程详尽介绍了利用Python进行人工智能操作的核心方法与应用场景,涵盖数据预处理、模型训练与评估全过程。通过源码解析和实战案例(如房价与股票价格预测),读者将学会构建与测试AI模型,并理解其优缺点。教程还探讨了AI在智能客服与医疗诊断等领域的应用,以及如何通过单元测试确保代码质量。通过本教程,初学者能够快速掌握AI基本技能,为未来的技术发展奠定坚实基础。
434 4
从零开始学AI:Python完整操作教程
|
5月前
|
运维 数据库 网络架构
详尽分享运维网络面试题101道
详尽分享运维网络面试题101道
205 0
|
2月前
|
安全 数据安全/隐私保护 Windows
数据安全的守护者:备份工具和恢复方法详解
数据安全的守护者:备份工具和恢复方法详解
94 6
|
6月前
|
缓存 算法 安全
深入理解操作系统:虚拟内存管理的原理与实践
【4月更文挑战第8天】 在现代计算机系统的设计与实现中,虚拟内存管理是操作系统核心功能之一。通过抽象物理硬件的细节,提供给用户一个看似无限的地址空间,它允许多个进程独立运行,同时为系统提供必要的内存保护机制。本文将探讨虚拟内存的基本原理、关键组件以及它在操作系统中的实际应用,旨在为读者提供一个清晰的视角来理解这一复杂的技术概念,并讨论其对现代计算环境的重要性和影响。
185 0
|
6月前
|
前端开发 网络协议 Java
Netty | 工作流程图分析 & 核心组件说明 & 代码案例实践
Netty | 工作流程图分析 & 核心组件说明 & 代码案例实践
358 0
|
安全 Unix Linux
开源软件的崛起:历史与未来
开源软件的崛起:历史与未来
230 0
|
2天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
18天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
22天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
13天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。