再说 JavaScript中this 对象 (超详细)

😉 你好呀,我是爱编程的Sherry,很高兴在这里遇见你!我是一名拥有十多年开发经验的前端工程师。这一路走来,面对困难时也曾感到迷茫,凭借不懈的努力和坚持,重新找到了前进的方向。我的人生格言是——认准方向,坚持不懈,你终将迎来辉煌!欢迎关注我😁,我将在这里分享工作中积累的经验和心得,希望我的分享能够给你带来帮助。

引言

在 JavaScript 中,this 是一个非常特殊且灵活的关键字,它的值取决于函数调用的上下文,即代码执行时的具体环境。this 的值不在编写时静态决定,而是在运行时动态绑定,它会指向当前函数执行的上下文对象。以下是对 this 的详细理解。

1. this 的定义

this 是一个指针,它指向调用当前函数的对象,而不是函数本身。在不同的上下文中,this 的指向是不同的。this 的值在函数执行时决定,不在函数定义时确定。

2. this 的几种常见情况

2.1 全局上下文中的 this

全局作用域普通函数调用中,this 指向全局对象。在浏览器中,全局对象是 window,在 Node.js 中是 global

console.log(this); // 在浏览器中,指向 window 对象

function show() {
  console.log(this); // 在全局函数中,this 也是指向 window
}

show(); // 输出:window

严格模式 ('use strict') 下,全局函数中的 this 会是 undefined

'use strict';
function show() {
  console.log(this); // 在严格模式下,this 是 undefined
}

show(); // 输出:undefined
2.2 对象方法中的 this

this 作为对象方法被调用时,this 指向的是调用该方法的对象。

const person = {
  name: 'Alice',
  sayHello: function() {
    console.log(this.name); // this 指向 person 对象
  }
};

person.sayHello(); // 输出:Alice

注意: 对象方法中的 this 指向调用方法的对象,而不是定义该方法的地方。

2.3 构造函数中的 this

在使用构造函数创建对象时,this 会指向新创建的对象。构造函数的主要功能就是初始化新对象。

function Person(name) {
  this.name = name;
}

const john = new Person('John');
console.log(john.name); // 输出:John

在这个例子中,this 指向的是新创建的 Person 实例 john

2.4 call、apply、bind 改变 this 的指向

JavaScript 提供了 callapplybind 方法,它们允许你显式地设置 this 的指向。

call 和 apply

callapply 都可以改变函数执行时 this 的指向,区别在于它们传递参数的方式不同:call 接受参数列表。 apply 接受一个参数数组。

function greet(greeting) {
  console.log(greeting + ', ' + this.name);
}

const person = { name: 'Alice' };
greet.call(person, 'Hello'); // Hello, Alice
greet.apply(person, ['Hi']); // Hi, Alice
bind

bind 方法返回一个新的函数,并且该函数的 this 永远绑定为指定的对象,除非再次使用 bind

function greet() {
  console.log(this.name);
}

const person = { name: 'Alice' };
const greetPerson = greet.bind(person);
greetPerson(); // 输出:Alice
2.5 箭头函数中的 this

箭头函数不绑定自己的 this,它会继承定义时所在上下文的 this,而不是执行时的 this。因此,它在很多情况下非常适合避免传统函数中的 this 指向问题。

const person = {
  name: 'Alice',
  sayHello: function() {
    const innerFunc = () => {
      console.log(this.name); // 箭头函数没有自己的 this,继承自外部的 this
    };
    innerFunc();
  }
};

person.sayHello(); // 输出:Alice

在这个例子中,innerFunc 是箭头函数,它继承了 sayHello 方法中的 this,即 person 对象。

2.6 事件处理函数中的 this

在 DOM 事件处理函数中,this 指向触发事件的 DOM 元素。

const button = document.querySelector('button');

button.addEventListener('click', function() {
  console.log(this); // this 指向被点击的按钮元素
});

如果在事件处理函数中使用箭头函数this 将不再指向 DOM 元素,而是指向定义时的外部上下文。

button.addEventListener('click', () => {
  console.log(this); // this 继承自外层作用域,通常是 window
});

3. 总结 this 在不同情况下的表现

使用场景this 指向
全局作用域在非严格模式下指向 window,严格模式下是 undefined
对象方法指向调用该方法的对象
构造函数指向新创建的对象
箭头函数继承自定义时的外部作用域 this
事件处理器指向触发事件的 DOM 元素
call/apply显式指定的 this
bind返回绑定了指定 this 的新函数

4. 常见 this 指向问题与解决方法

4.1 失去上下文的 this

一个常见的问题是在回调函数或异步执行时,this 的指向变得不明确。例如:

const person = {
  name: 'Alice',
  sayHello: function() {
    setTimeout(function() {
      console.log(this.name); // `this` 在此处指向全局对象(在浏览器中是 window)
    }, 1000);
  }
};

person.sayHello(); // 输出:undefined (因为 this 指向 window)

解决方法:

使用 箭头函数 来保持 this 的指向:

person.sayHello = function() {
  setTimeout(() => {
    console.log(this.name); // `this` 指向 person 对象
  }, 1000);
};

person.sayHello(); // 输出:Alice

使用 bind 绑定正确的 this

person.sayHello = function() {
  setTimeout(function() {
    console.log(this.name);
  }.bind(this), 1000); // 使用 bind 确保 this 指向 person
};

person.sayHello(); // 输出:Alice
4.2 方法作为回调时的 this 丢失

当你将一个对象的方法作为回调函数传递时,this 的指向可能会丢失,导致错误的上下文:

const person = {
  name: 'Alice',
  sayHello: function() {
    console.log(this.name);
  }
};

const greet = person.sayHello;
greet(); // 输出:undefined,因为 this 指向全局对象

解决方法:

使用 bind 显式绑定 this

const greetBound = person.sayHello.bind(person);
greetBound(); // 输出:Alice

5. 总结

this 是 JavaScript 中动态绑定的关键字,取决于函数调用的方式和上下文。在全局作用域下,this 指向全局对象;在对象方法中,this 指向调用该方法的对象;在构造函数中,this 指向新创建的对象。箭头函数不会绑定自己的 this,它继承定义时的上下文 this,而 callapplybind 可以显式地改变 this 的指向。this 的灵活性虽然强大,但也常常是初学者的困惑点,理解 this 的工作机制有助于编写更健壮的 avaScript 代码。

这段代码是一个基于 JavaScript 的事件监听器片段,主要用来捕获自定义事件并根据接收到的数据执行相应操作。下面是逐行逐段的详细解析: --- ### 第一行: ```javascript window.document.addEventListener("czcbDeepSeekVoiceValue", async (res) => { ``` - **功能**:为 `document` 对象绑定一个名为 `"czcbDeepSeekVoiceValue"` 的自定义事件监听器。 - **说明**: - 自定义事件是由开发者手动创建并通过 `dispatchEvent` 或类似方式触发的事件类型。 - 此处的事件名称是 `"czcbDeepSeekVoiceValue"`,表明这是一个与语音识别或输入相关的事件。 - 回调函数被声明为异步 (`async`) 函数,这意味着如果后续逻辑中有需要等待的操作(如 API 请求),可以直接使用 `await` 关键字简化代码结构。 --- ### 第二至第四行: ```javascript if (res.data.voiceText) this.aivoice(res.data.voiceText); else toast(this.$i18n.t("aibank['抱歉没有听清,请再说一遍']")); ``` #### 具体分析如下: 1. **检查是否存在有效的语音文本数据**: ```javascript if (res.data.voiceText) ``` - 接收事件传递过来的对象 `res` 中包含了一个字段 `data`,而 `data` 内部有一个子属性 `voiceText`。 - 如果该属性存在并且有有效值,则表示成功接收到了用户的语音转文字内容。 2. **处理成功的语音文本**: ```javascript this.aivoice(res.data.voiceText); ``` - 调用当前对象的方法 `aivoce()`,并将提取到的 `voiceText` 数据作为参数传入。 - 这里的具体逻辑未展示,但可以根据命名推测此方法可能是将用户的语音转化为 AI 提供的服务响应的一部分。 3. **当无法识别语音时提示用户**: ```javascript else toast(this.$i18n.t("aibank['抱歉没有听清,请再说一遍']")); ``` - 如果未能从事件中获取有效的语音文本,则调用全局工具方法 `toast()` 显示一条消息给用户。 - 使用国际化插件 `$i18n` 获取对应语言的消息字符串 `"aibank['抱歉没有听清,请再说一遍']"`. - $i18n 是常见的 Vue.js 插件库中的组件化翻译解决方案,允许根据不同地区的设置加载不同的语言包。 - `'aibank'` 表明这是专属于银行领域或某特定业务模块下的语句标识符。 --- ### 总结 整体来看,上述代码的功能可以概括如下: - 注册监听器以监控来自外部来源(可能是本地 SDK或者是第三方服务API )发出的声音识别完成之后广播出来的“ czcbDeepSeekVoiceValue ”类型事件; - 收集到此类通知后,依据携带的实际资料状况采取下一步行动——若发现可用的结果即启动关联的人工智能回应机制;反之则利用友好的界面提醒手段告知参与者再次尝试发音过程 。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sherry Tian

打赏1元鼓励作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值