首页 > 编程语言 >JavaScript 内的 this 指向

JavaScript 内的 this 指向

时间:2023-04-18 13:22:10浏览次数:41  
标签:function 调用 console 函数 指向 JavaScript fn log

 在 javascript 语言中, 有一个奇奇怪怪的 "关键字" 叫做 this

● 为什么说它是 奇奇怪怪 呢, 是因为你写出 100 个 this, 可能有 100 个解释, 完全不挨边

● 但是, 在你的学习过程中, 搞清楚了 this 这个玩意, 那么会对你的开发生涯有很大帮助的

● 接下来咱们就开始一点一点的认识一下 this

this 初认识
● 看到 this, 先给他翻译过来 "这个"

● 到底啥意思呢 ?

 饭桌上, 你妈和你说, 你多吃点的这个

 商店里, 你媳妇和你说, 这个包 这个包 这个包 我都要

 宴会上, 你爸和人介绍说, 这个傻小子是我儿子

● 你看, 每一句话上都有 "这个", 但是每个 "这个" 都是一个意思吗 ? 并不

● 就像我们 js 内的 this 一样, 每一个 this 的意思都不一样

● 但是我们会发现

 在说话的过程中, "这个" 是和我们说话的手势有关系

● 在 js 内一个道理

 this 的意思是和代码的 "手势" 有关系

● 例子 :

 当你媳妇手指着一个 LV 包的时候, 说的 "这个" 指代的就是 LV包`

 当你妈指着鱼香肉丝的时候说 "这个" 指代的就是 鱼香肉丝

 所以在 javascript 内的 this 是要看 "说这句话的代码手指向哪里了"

● 看看下面一段代码

var box = document.querySelector('#box')

box.onclick = function () {
console.log(this)
}

 当你点击 box 这个元素的时候, 会触发后面的函数

 然后函数一执行, 就会在控制台打印一下 this

 这里的 this 就是 box 这个元素

● 这就是一个非常简单的 this 指向的例子了

● 接下来我们就开始详细学习一下 this

给你个概念
● this , 是一个指针形变量, 它动态的指向当前函数的运行环境

● "什么鬼东西, 我听不懂啊"

● 给一个私人的解释 : "根据 this 所在的函数是如何被调用的来决定 this 是什么"

● 举个栗子来看一下

function fn() {
console.log(this)
}
fn()

// this 就是 window

● 因为 this 是在 fn 函数内, 所以 fn 函数的调用方式就决定了这个 this 是什么

function a() {
function b() {
console.log(this)
}
b()
}
a()

// this 就是 window

 因为 this 是在 b 函数内, 所以 b 函数的调用方式决定了 this 是什么, 和 a 函数没关系

● 就是这个意思

● 最后, 根据这些年的经验总结给出一个私人的概念, 要牢记

 函数的 this

 和函数定义在哪没关系

 和函数怎么定义没关系

 只看这个函数的调用方式

 箭头函数除外

对象调用
● 对象调用, 就是利用一个对象作为宿主来调用函数

● 最简单的方式就是把函数写在一个对象内, 利用对象来调用

// 对象内写一个函数
const obj = {
fn: function () { console.log(this) }
}

// 调用这个函数
obj.fn()

 这时候, 我们调用了和这个对象内的 fn 函数

 调用方式就是利用对象调用的函数, 所以在这个函数内的 this 就是 obj 这个对象

    ○  换句话说, 只要在这个函数内, 只要出现 this 就是这个对象

全局调用
● 顾名思义, 全局调用就是直接调用一个全局函数

function fn() {
console.log(this)
}

fn()

 此时这个函数内的 this 就是 window

    ○  可能有的小伙伴觉得疯了

 但是我们仔细思考一下, 你会发现

 其实 fn 因为是在全局上的, 那么其实调用的完整写法可以写成 window.fn()

 此时就回到了之前对象调用那条路上, 这样就通顺了

奇怪的调用
● 这个时候, 有的小伙伴可能会想到一个问题, 如果这个函数不放在全局呢 ?

const obj = {
fn: function () {
function fun() {
console.log(this)
}

fun()
}
}

obj.fn()

● 此时的 this 应该是什么呢 ?

● 按照之前的思路思考

 obj.fn() 确实调用了函数, 但是 this 不是在 obj.fn 函数内, 是在 fun 函数内

 fun() 确实也调用了函数, 但是我没有办法写成 window.fun()

 那么 this 到底是不是 window 呢, 还是应该是 obj 内

● 答案确实是 window, 这又是为什么呢 ?

捋一下思路
● 说道这里, 我们会发现

● this 真的是好奇怪哦 o(* ̄︶ ̄*)o 搞不定了

● 要是按照这个方式, 我来回来去的得记多少种, 谁会记得下来呢

● 接下来(划重点)

   我用我代码三十年的经验给你总结出来了一些内容, 希望你能牢记

this 的个人经验
● 首先, this 在各种不同的情况下会不一样

● 那么从现在开始我把我总结的内容毫无保留的传授给你

经验一 :
● 在 js 的非严格模式下适用

● 在非箭头函数中适用

● 不管函数定义在哪, 不管函数怎么定义, 只看函数的调用方式

 只要我想知道 this 是谁

 就看这个 this 是写在哪个函数里面

 这个函数是怎么被调用的

观察 this 在哪个函数内
function fn() {
console.log(this)
}

// this 在函数 fn 内, 就看 fn 函数是怎么被调用的就能知道 this 是谁

const obj = {
fn: function () {
console.log(this)
}
}

// this 在 obj.fn 函数内, 就看这个函数怎么被调用的就能知道 this 是谁

const obj = {
fn: function () {
function fun() {
console.log(this)
}
}
}

// 这个 this 是在 fun 函数内
// 如果你想知道这个 this 是谁
// 和 obj.fn 函数没有关系, 只要知道 fun 函数是怎么被调用的就可以了

● 一定要注意 : 你想知道的 this 在哪个函数内, 就去观察哪个函数的调用方式就好了

一些常见的函数调用方式
1. 普通调用
 调用方式 : 函数名()

 this 是 window

 只要你书写 "函数名()" 调用了一个函数, 那么这个函数内的 this 就是 window

function fn() {
console.log(this)
}
fn()
// 这里就是 fn() 调用了一个函数, 那么 fn 内的 this 就是 window

const obj = {
fn: function () {
function fun() {
console.log(this)
}
fun()
}
}
obj.fn()
// 这里的 this 因为是在 fun 函数内
// fun() 就调用了这个 fun 函数
// 所以不用管 fun 函数写在了哪里
// 这个 fun 函数内的 this 就是 window

2. 对象调用
 调用方式:

 对象.函数名()

 对象['函数名']()

● this 就是这个对象, 对象叫啥, 函数内的 this 就叫啥

const obj = {
fn: function () {
console.log(this)
}
}
obj.fn()
// 因为 obj.fn() 调用了这个函数, 所以 obj.fn 函数内的 this 就是 obj

const xhl = {
fn: function () {
console.log(this)
}
}
xhl.fn()
// 因为 obj.fn() 调用了这个函数, 所以 xhl.fn 函数内的 this 就是 xhl

function fn() {
const xhl = {
fn: function () {
console.log(this)
}
}
xhl.fn()
}

fn()
// 因为我们要观察的 this 是在 xhl.fn 这个函数内
// 所以只需要关注这个函数是如何被调用的即可
// 因为是 xhl.fn 调用了和这个函数, 所以函数内的 this 就是 xhl

3. 定时器调用
 调用方式

 setTimeout(function () {}, 1000)

 setInterval(function () {}, 1000)

 this 就是 window

 一个函数不管是怎么定义的, 只要被当做定时器处理函数使用, this 就是 widnow

setTimeout(function () {
console.log(this)
}, 1000)
// 这里的 this 就是 window

setInterval(function () {
console.log(this)
}, 1000)
// 这里的 this 就是 window

const xhl = {
fn: function () {
console.log(this)
}
}

setTimeout(xhl.fn, 1000)
// 这里的 xhl.fn 函数不是直接书写 xhl.fn() 调用的
// 而是给到了 setTimeout 定时器处理函数
// 所以这里的 this 就是 window

4. 事件处理函数
 调用方式

 事件源.on事件类型 = 事件处理函数

 事件源.addEventListener(事件类型, 事件处理函数)

 this 就是 事件源

 只要是作为事件处理函数使用, 那么该函数内的 this 就是 事件源

   奥,对了,事件就是:在事件中,当前操作的那个元素就是事件源

box.onclick = function () {
console.log(this)
}
// 这里的 this 就是 box

box.addEventListener('click', function () {
console.log(this)
})
// 这里的 this 就是 box

const xhl = {
fn: function () {
console.log(this)
}
}

box.addEventListener('click', xhl.fn)
// 这里的 xhl.fn 函数不是直接书写 xhl.fn() 调用的
// 而是给到了 事件, 被当做了事件处理函数使用
// 所以这里的 this 就是 事件源box

const xhl = {
fn: function () {
console.log(this)
}
}

box.onclick = xhl.fn
// 这里的 xhl.fn 函数不是直接书写 xhl.fn() 调用的
// 而是给到了 事件, 被当做了事件处理函数使用
// 所以这里的 this 就是 事件源box

5. 构造函数调用
 调用方式

 new 函数名()

 this 就是该构造函数的当前实例

 只要和 new 关键字调用了, this 就是实例对象

function fn() {
console.log(this)
}

const f = new fn()
// 这里的因为 fn 函数和 new 关键字在一起了
// 所以这里的 this 就是 fn 函数的实例对象
// 也就是 f

const xhl = {
fn: function () {
console.log(this)
}
}

const x = new xhl.fn()
// 这里的 xhl.fn 也是因为和 new 关键字在一起了
// 所以这里的 this 就是 xhl.fn 函数的实例对象
// 也就是 x

记清楚原则 :
不管函数在哪定义

不管函数怎么定义

只看函数的调用方式

经验二 :
● 在严格模式下适用

● 其实只有一个

 全局函数没有 this, 是 undefined

 其他的照搬经验一就可以了

1. 非严格模式
// 非严格模式
function fn() {
console.log(this)
}
fn()
// 因为是在非严格模式下, 这里的 this 就是 window

2. 严格模式
// 严格模式
'use strict'
function fn() {
console.log(this)
}
fn()
// 因为是在严格模式下, 这里的 this 就是 undefined

记清楚原则 :
严格模式下

全局函数没有 this

是个 undefiend

经验三 :
● 专门来说一下箭头函数

● 其实也只有一条

 推翻之前的所有内容

 箭头函数内没有自己的 this

 箭头函数内的 this 就是外部作用域的 this

● 换句话说, 当你需要判断箭头函数内的 this 的时候

 和函数怎么调用没有关系了

 要看函数定义在什么位置

// 非箭头函数
const xhl = {
fn: function () {
console.log(this)
}
}
xhl.fn()
// 因为是 非箭头函数, 所以这里的 this 就是 xhl

// ==========================================================

// 箭头函数
const xhl = {
fn: () => {
console.log(this)
}
}
xhl.fn()
// 因为是 箭头函数, 之前的经验不适用了
// 这个函数外部其实就是全局了, 所以这里的 this 就是 window

// 非箭头函数
box.onclick = function () {
console.log(this)
}
// 因为是 非箭头函数, 这里的 this 就是 box

// ==========================================================

// 箭头函数
box.onclick = () => {
console.log(this)
}
// 因为是 箭头函数
// 这个函数外部就是全局了, 所以这里的 this 就是 window

// 非箭头函数
const obj = {
fn: function () {
function fun() {
console.log(this)
}
fun()
}
}
obj.fn()
// 因为是 非箭头函数, 所以 fun 函数内的 this 就是 window

// ==========================================================

// 箭头函数
const obj = {
fn: function () {
const fun = () => {
console.log(this)
}
fun()
}
}
obj.fn()
// 因为是 箭头函数
// 那么这个 fun 外面其实就是 obj.fn 函数
// 所以只要知道了 obj.fn 函数内的 this 是谁, 那么 fun 函数内的 this 就出来了
// 又因为 obj.fn 函数内的 this 是 obj
// 所以 fun 函数内的 this 就是 obj

记清楚原则 :
只要是箭头函数

不管函数怎么调用

就看这个函数定义在了哪里

最后
 好了

 按照以上三个经验, 记清楚原则

 那么在看到 this 就不慌了

标签:function,调用,console,函数,指向,JavaScript,fn,log
From: https://www.cnblogs.com/qian-fen/p/17329219.html

相关文章

  • 使用JavaScript的原型
    在javascript中,函数可以有属性。每个函数都有一个特殊的属性叫作原型(prototype)。functiondoSomething(){}console.log(doSomething.prototype);运行这段代码之后,控制台上面应该出现了像这样的一个对象。{constructor:ƒdoSomething(),__proto__:{const......
  • JavaScript 利用 async await 实现 sleep 效果
    constsleep=(timeountMS)=>newPromise((resolve)=>{setTimeout(resolve,timeountMS);});(async()=>{console.log('11111111,'+newDate());awaitsleep(2000);console.log('22222222,'+newDate());await......
  • javascript
    1970.1.1互联网开始时间**JavaScript(开发Web页面的脚本语言)**是面向Web的编程语言,获得了所有网页浏览器的支持,是目前使用最广泛的脚本编程语言之一,也是网页设计和Web应用必须掌握的基本工具。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最......
  • JavaScript对象
    JavaScript对象的定义无序属性的集合,其属性可以包含基本值、对象或者函数严格来说对象是一组没有特定顺序的值对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。(可以把对象想象成散列表:一组名值对,其中值可以是数据或函数)......
  • python s12 day13 JavaScript、Dom和jQuery
    1.JavaScriptJavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理。1、JavaScript代码存在形式<!--方式一--><scripttype"text/javascript"src="JS文件"></script>......
  • 六大JavaScript使用小技巧
    之前写过一些关于编程的小技巧,今天已久写一些JS中用到的小技巧,非常实用,如果熟悉了实用起来相当快捷方便。1.类型强制转换1.1string强制转换为数字可以用*1来转化为数字(实际上是调用.valueOf方法)然后使用Number.isNaN来判断是否为NaN,或者使用a!==a来判断是否为NaN,因为......
  • 学习JavaScript 一
    文件引用在一个单独的js文件中也可以编写JavaScript代码,然后在HTML文件中使用script标签进行引用,以下是一个简单演示。   遍历对象枚举遍历对象中的属性,可以使用for…in语句循环,对象中有几个属性,循环体就会执行几次。语法格式:for(var变量in对象){}案例演示:......
  • js 传递汉字 乱码_JavaScript 字符串反转乱码问题解决
    https://blog.csdn.net/weixin_36483301/article/details/113451892emoji表情和非常用字实际解决中文编码问题,可以通过解码解决js中使用decodeURL即可解决......
  • javascript 把嵌套的 map 转成 object,再转 json 字符串
    使用JSON.stringify转map时发现并没有转成想要的JSON数据,搜索发现要转成Object才能够转成完整的JSON,用递归转换:constconvertNestedMapToObject=(map)=>{if(mapinstanceofMap){map.forEach((v,k)=>{......
  • javascript常用的循环对比及性能分析
    结论:js中的for循环只有在处理百万条数据以上才会展示出他的强大性能,和看出明显优势,但是在百万条数据往下甚至到个位数的数据量通常都是for和while还有do...while不相上下,反而后两者更加优势明显下面是测试耗时截图(在不同浏览器也会有所不同,我这是Chrome版本111.0.5563.149)......