好程序员Web前端培训分享如何讲清楚this指向?

简介:

  好程序员Web前端培训分享如何讲清楚this指向?不得不说,要搞清楚this是需要一个前提的。

  你首先得知道函数、对象、作用域等基本概念。

  知道 call、apply、bind方法那再好不过了

  当然学好语文是很重要的

  需要知道第一人称和第二人称和第三人称的区别

先来看一个新闻:

“我体内的恶魔已被锁住了这么多年,现在这种锁链已经松了。”
“我很害怕,很孤独,很疑惑,我将要向导致我的痛苦的根源——社会作出反击,我想尽我所能地去伤害这个社会,然后死去。”

这段令人不寒而栗的文字,是美国北达科他州系列杀人案嫌犯约瑟夫·邓肯于2005年5月11日写下的。当人们在近两个月后看到这段文字时,他已经将一个 5口之家的3人残忍地杀害,并绑架了另外2名分别为8岁和9岁的孩子。

假设,你是一个jc,抓到了一个xf
然后你在他的家里搜出这本日记,此时你作何感想?

你肯定会想,如果这是嫌疑人自己写的,这不就等于认罪了嘛?

当然,犯罪嫌疑人也可以狡辩说,这日记根本不是我写的,只是我从网上摘抄的段子

我们试着把日记稍作改动,看看会有什么效果变化。

他体内的恶魔已被锁住了这么多年,现在这种锁链已经松了。他很害怕,很孤独,很疑惑,他将要向导致他的痛苦的根源——社会作出反击,他想尽他所能地去伤害这个社会,然后死去。

注意到了吗?

把第一人称改成了第三人称

这看上去根本不像日记,更像是一个小说故事。

为什么一个字的改动会有这么大差别呢?

带着对这个问题的思考, 我们来开始今天this指向的学习。

this的英文含义
先看英文解释 this: 这样、这个

接下来看一段代码

var obj = {

show : function(){

    console.log(this);

}}obj.show();

结果很容易预测,打印obj对象本身

在JS中,this属于一个关键字,也就是可以理解为,它是一个系统自带命令

通常,我们把它的含义解释为:当前对象

那么问题来了: 当前对象到底是指谁呢?

在上面的代码案例中,this代表的就是obj这个对象

接下来我们再看一段代码

function show(){

console.log(this);}show();

结果打印window对象

如果你对这个打印结果感到奇怪,那么可能你忽略了一个常识问题

window对象是可以省略不写的!

所以,上面的代码,实际上等价于:

function show(){

console.log(this);}window.show();

我再举一个常见的例子,关于事件绑定

btn.onclick = function(){

console.log(this);}btn.onclick();   //手动调用函数//除手动调用外,鼠标单击按钮也可以触发函数执行

最终,无论是手动调用,还是单击按钮调用

打印结果都是btn对象

我们似乎总结出了一个this指向的规律
this总是指向,调用该函数的对象

如果你的代码结构是这样的

对象.函数();

那么,函数里的this,必然指向这个对象本身!

假设这个结论是成立的, 我们不妨来验证一下我们的猜想!!

function show(){

console.log(this);}window.show();  //打印window对象var obj1 = {};obj1.show1 = show;obj1.show1();  //打印obj1对象var obj2 = {};obj2.show2 = obj1.show1;obj2.show2();  //打印obj2对象

从上面代码的例子中,可以看出来

window对象和obj1对象和obj2对象,共享了一个函数 show

window.show == obj1.show1; //truewindow.show == obj2.show2; //true

三个对象,用了同一个函数

但打印出的this是各不相同的

window.show(); 打印出window对象

obj1.show1(); 打印出obj1对象

obj2.show2(); 打印出obj2对象

这似乎再一次印证了,我们刚才的猜想:

函数由哪个对象调用,this就指向哪个对象

科学是严谨的,得出结论之前,我们还是要反复验证
再看一个例子:

btn.onclick = function(){

setTimeout(function(){

    console.log(this);

},0)}btn.onclick();

实际上,我只是在原来代码的基础上,增加了一个延迟器,并且时间设为0

那么打印出的this会不会有变化呢??

你可以先思考一番

通常按照直觉,我们会认为,延迟器只是延缓了执行时间,打印结果依然还是btn对象,没有变化

但经过测试发现,实际的打印结果,是 window对象

是我们刚才的猜想错了吗?

要解释这个现象,我们得重新来观察这段代码

btn.onclick = function(){ //<----这个函数,用A来表示 setTimeout(function(){ //<----这个函数,用B来表示 console.log(this);

},0)}btn.onclick();

注意代码当中出现了两个函数,我们分别起名字叫做函数A和函数B

按照我们刚才的猜想: 函数由哪个对象调用,this就指向哪个对象

所以,this指向会依赖它所在的函数

而这个函数,到底是 函数A还是函数B呢?

其实你不难从代码中看的出来, this很明显是在函数B中的

所以, 结果没有打印出 btn, 现在我们也不感到奇怪了

因为, this已经不再函数 A的内部了,而是函数B的内部

你可能还要问,为什么函数B里的 this指向window呢?

这里其实算是一个特例,传入定时器的函数,由哪个对象调用,我们不得而知

这种情况,this就指向window

你暂时记住这个规律就好了,等你学完了作用域链,你就会明白其中的本质

回到我们开头的新闻
假设日记就是嫌疑人写的。 但日记里全是第三人称。那么 『 他 』到底是谁就很难说了

反过来如果日记里用的都是第一人称写的。 那么 『 我 』肯定指的是嫌疑人自己

JS函数当中的this关键字, 就相当于我们说话中的第一人称代词我

例如这样一个例子:

A对B说:“我要杀了你!”

这里的『我』指代A, 『你』指代B

B对A说:”我要弄死你!”

这里的『我』指代B, 『你』指代A

所以你看,同样的一个字,它可以指代任何人,关键看从谁的嘴里说出来

function fn(){

//this, 就相当于中文里的我    //不要上来就问this会指向谁    //我们必须搞清楚上下文环境,fn是谁调用的?(相当于这句话从谁的嘴里说出来)    //如果我们不能弄清楚这个问题,讨论this指向就没有意义    console.log(this);}

到目前为止,我们差不多可以得出结论了
下面用几个练习最终验证一下
var obj = {

show: function(){

    console.log(this);

}}

上面的代码,最终打印obj对象
无论经过多少曲折,我们最终只看一个结论,那就是:

this所在的函数,由哪个对象调用?

我把代码进一步改造

function fn(){

console.log(this);}

var obj = {

show: fn}

btn.onclick = function(){

window.setTimeout(function(){

    obj.show();

}, 100);}

上面的代码,最终打印还是obj对象

当然了,也总会有一些例外情况, 比如下面这个:

function m1(){

function m2(){

    console.log(this);

}

m2();}m1();

我们不禁要问,函数m2是由哪个对象调用的?

我们想尽了各种可能,最终发现都是错的。

我们始终不知道这个m2由哪个对象调用,好像它就那样执行了

而实际的打印结果呢?

不出意外,还是window对象

最后的结论

  1. 所有的this关键字,在函数运行时,才能确定它的指向
  2. this所在的函数由哪个对象调用,this就会指向谁
  3. 当函数执行时,没有明确的调用对象时,则this指向window
    由this衍生出的问题

刚才遗留了一个问题没有解决

btn.onclick = function(){

setTimeout(function(){

    console.log(this);

},0)}btn.onclick();

我们期待this指向btn,而this现在却指向了window

这个问题该怎么修复呢? 有很多办法

如果你不知道call、apply、bind,那么恐怕你只能看得懂方法A

//方法Abtn.onclick = function(){

var self = this; //使用变量保存this,self变量的值是不会随着环境改变的    setTimeout(function(){

    console.log(self);  

},0)}btn.onclick();

//方法Bbtn.onclick = function(){

var self = this; //使用变量保存this 

function fn(){  //将代码写在一个函数fn中        console.log(this);

}
setTimeout(function(){

    fn.call(self); //强行指定this为self对象    },0)}btn.onclick();/*  call方法的作用,是调用函数,同时指定this可以代表谁  例如 fn.call(obj)  意思就是 调用函数fn,并且this指向obj对象*/

//方法Cbtn.onclick = function(){

var self = this; //使用变量保存this 

function fn(){  //将代码写在一个函数fn中        console.log(this);

}
setTimeout(function(){

    fn.apply(self); //使用apply方法调用函数,强行指定this为self对象    },0)}btn.onclick();/*  apply方法的作用,是调用函数,同时指定this可以代表谁  例如 fn.apply(obj)  意思就是 调用函数fn,并且this指向obj对象*/

//方法Dbtn.onclick = function(){

setTimeout(function(){

    console.log(this);

}.bind(this), 0 )

//使用bind方法,将定时器函数的this强行绑定为事件函数的this}btn.onclick();/*  bind方法的作用,是绑定函数的this,同时返回绑定后的新函数  例如   var fb = fn.bind(obj);  window.fb();  无论谁调用fb函数, 函数的this都会指向obj*/

接下来的内容,请学完ES6的箭头函数再来看吧

  1. 如何判断箭头函数的this?

因为箭头函数不具备自己的this,所以非常简单,假装它不存在,就像这样:

这下this的指向非常清晰了吧

_1

  1. 箭头函数可以用call来改变this指向吗?

不能!! 试图改变箭头函数的this是徒劳的。
_2

最后一个特例:构造函数

  1. 什么是构造函数?

假设有一个函数Fn, 我们有两种方式来调用它

普通的调用 Fn()
配合new关键字来调用 new Fn()
第二种调用方式, 函数就变成了构造函数


注意,在构造函数中, 上面我们所讲的结论,是不成立的!!


  1. 那构造函数里的this是谁呢?

请期待下一篇文章《构造函数与class》

相关文章
|
11月前
|
并行计算 前端开发 JavaScript
Web Worker:让前端飞起来的隐形引擎
在现代 Web 开发中,前端性能优化是一个至关重要的课题,尤其是对于计算密集型的应用,如图像处理、视频处理、大规模数据分析等任务。单线程的 JavaScript 引擎常常成为性能瓶颈,导致应用变得迟缓。Web Worker,作为一种强大的技术,使得前端能够在后台进行并行计算,从而实现高效的任务处理,不影响主线程的运行和用户的交互体验。
856 108
|
11月前
|
JavaScript 前端开发 Java
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
845 72
前端框架选择之争:jQuery与Vue在现代Web开发中的真实地位-优雅草卓伊凡
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
494 3
|
前端开发 JavaScript
探索现代Web应用的微前端架构
【10月更文挑战第40天】在数字时代的浪潮中,Web应用的发展日益复杂多变。微前端架构作为一种新兴的设计理念,正逐步改变着传统的单一前端开发模式。本文将深入探讨微前端的核心概念、实现原理及其在实际项目中的应用,同时通过一个简单的代码示例,揭示如何将一个庞大的前端工程拆分成小而美的模块,进而提升项目的可维护性、可扩展性和开发效率。
|
移动开发 前端开发 JavaScript
前端web创建命令
本项目使用 Vite 搭建 Vue + TypeScript 开发环境,并基于 HTML5 Boilerplate 提供基础模板,快速启动现代前端开发。
253 2
|
Web App开发 编解码 移动开发
零基础音视频入门:你所不知道的Web前端音视频知识
本文回顾了Web端音视频的发展历程,同时还介绍了视频的编码、帧率、比特率等概念,提到了Canvas作为视频播放的替代方案,以及FFmpeg在音视频处理中的重要作用等知识。
368 1
|
人工智能 前端开发 JavaScript
AI程序员:通义灵码 2.0应用VScode前端开发深度体验
AI程序员:通义灵码 2.0应用VScode前端开发深度体验,在软件开发领域,人工智能技术的融入正深刻改变着程序员的工作方式。通义灵码 2.0 作为一款先进的 AI 编程助手,与广受欢迎的代码编辑器 Visual Studio Code(VScode)相结合,为前端开发带来了全新的可能性。本文将详细分享通义灵码 2.0 在 VScode 前端开发环境中的深度使用体验。
2610 2
AI程序员:通义灵码 2.0应用VScode前端开发深度体验
|
前端开发
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
1268 1
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
|
前端开发 JavaScript 搜索推荐
HTML与CSS在Web组件化中的核心作用及前端技术趋势
本文探讨了HTML与CSS在Web组件化中的核心作用及前端技术趋势。从结构定义、语义化到样式封装与布局控制,两者不仅提升了代码复用率和可维护性,还通过响应式设计、动态样式等技术增强了用户体验。面对兼容性、代码复杂度等挑战,文章提出了相应的解决策略,强调了持续创新的重要性,旨在构建高效、灵活的Web应用。
476 6
|
监控 前端开发 JavaScript
探索微前端架构:构建可扩展的现代Web应用
【10月更文挑战第29天】本文探讨了微前端架构的核心概念、优势及实施策略,通过将大型前端应用拆分为多个独立的微应用,提高开发效率、增强可维护性,并支持灵活的技术选型。实际案例包括Spotify和Zalando的成功应用。

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1243
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    556
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    428
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    430
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    543
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    720
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1403
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    312
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1166
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    501