深入理解JavaScript中的this与箭头函数

JavaScript中this是一个令人困惑但关键的概念,它在不同的绑定下指向不同的对象或值。在本文中,我们将探讨五种绑定规则,并介绍箭头函数是如何在本文this中语境中表现的。

一、为什么用this?

一句话,简化代码的书写。学习 this 是 JavaScript 中至关重要的一部分,因为它影响着代码中函数的行为,尤其是在面向对象和事件处理等方面。

二、this的五种规则

1.默认绑定规则

默认绑定规则非常简单:函数在哪个词法作用域中生效,this就指向哪里。当一个函数独立调用时,this默认指向全局对象,通常是下面window(浏览器环境)。以下是一个例子:

scss 复制代码
function globalFunction() {
  console.log(this); // 在浏览器中输出 window
}

globalFunction();

2. 隐式绑定规则

当一个函数被对象所拥有时,且调用时,函数的this指向该对象。这就是隐式绑定。考虑以下例子:

javascript 复制代码
const myObject = {
  prop: "I am part of the object",
  myMethod: function () {
    console.log(this.prop);
  }
};

myObject.myMethod(); // 输出 "I am part of the object"

3.隐式丢失

隐式丢失是指当函数被多个对象链式调用时,this指向引用函数的那个​​对象。如果函数被提取出来,this可能会失去原有的绑定。看一个示例:

ini 复制代码
const obj1 = {
  value: 42,
  getValue: function () {
    return this.value;
  }
};

const obj2 = {
  value: 17
};

const getValueFromObj2 = obj1.getValue.bind(obj2);
console.log(getValueFromObj2()); // 输出 17

4. new绑定

当使用new关键字调用函数时,this会指向新创建的实例对象。这种绑定方式常用于构造函数:

ini 复制代码
function Animal(name) {
  this.name = name;
}

const cat = new Animal("Fluffy");
console.log(cat.name); // 输出 "Fluffy"

5.显示绑定

通过callapplybind,我们可以显式地指定函数内部的this。下面我们将详细解析这三种方法:

1、call方法:

call方法用于调用具有指定this值和单独提供的参数的函数。这是一个例子:

javascript 复制代码
function greet(name) {
  console.log(`Hello, ${name}! My name is ${this.name}.`);
}

const person = { name: 'John' };

greet.call(person, 'Alice');
// 输出: Hello, Alice! My name is John.

在此示例中,call用于调用作为值的greet函数。值后面的附加参数(在本例中)将作为其参数传递给函数。

2、apply方法:

与 类似call,该apply方法用于调用具有指定this值和参数的数组或类数组对象的函数。这是一个例子:

javascript 复制代码
function add(a, b) {
  console.log(`${this.name} added: ${a + b}`);
}

const calculator = { name: 'CASIO' };

add.apply(calculator, [3, 7]);
// 输出: CASIO added: 10

在此示例中,apply用于调用作为值的add函数。第二个参数是一个数组,它作为单独的参数传递给函数。

3、bind方法:

bind方法创建一个具有指定this值和可选初始参数的新函数。但是,它不会立即调用该函数;相反,它返回一个可以稍后调用的新函数。这是一个例子:

javascript 复制代码
function displayInfo(age, city) {
  console.log(`${this.name} is ${age} years old and lives in ${city}.`);
}

const personInfo = { name: 'Jane' };

const boundFunction = displayInfo.bind(personInfo, 25);
boundFunction('New York');
// Output: Jane is 25 years old and lives in New York.

在此示例中,bind用于创建一个新函数 ( boundFunction),并将其personInfo作为this值和25初始参数。当boundFunction稍后用 调用时'New York',它将提供的参数附加到最初绑定的参数。

概括:

  • call this:调用具有指定值和单独参数的函数。
  • apply this:使用指定值和参数的数组或类似数组的对象调用函数。
  • bind :使用指定this值和可选初始参数创建一个新函数,但不立即调用该函数。

这些方法提供了管理this函数上下文的灵活性,允许开发人员控制函数在不同对象或上下文中的执行方式。

三、箭头函数的特殊性

在上面的例子中,箭头函数与普通函数在this上有所不同。箭头函数没有自己的this,它会捕获其外层的普通函数的this。考虑下面的例子:

ini 复制代码
function outerFunction() {
  const arrowFunction = () => {
    console.log(this);
  };

  arrowFunction();
}

const obj = { prop: "I am an object" };
outerFunction.call(obj); // 输出 { prop: "I am an object" }

在箭头函数中,this始终指向outerFunction被调用时的this,而不是箭头函数被调用时的this。这种特性使得箭头函数在某些情况下更容易理解和使用。同时也要注意!箭头函数不能做构造函数!

javascript 复制代码
var Foo = () => {
}
new Foo();
// 箭头函数不能做构造函数
//输出会报错

总结

理解JavaScript中的this是成为一个高效开发者的关键。通过默认绑定、隐式绑定、隐式丢失、显示绑定和new绑定,我们可以更好地掌握函数在不同上下文中的行为。同时,箭头函数的特殊性使得我们能够更方便地处理this问题,但也需要注意其与普通函数的差异。通过深入研究这些概念,我们能够写出更健壮、可维护的JavaScript代码。

相关推荐
若川40 分钟前
Taro 源码揭秘:10. Taro 到底是怎样转换成小程序文件的?
前端·javascript·react.js
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
醒了就刷牙1 小时前
黑马Java面试教程_P9_MySQL
java·mysql·面试
黑客老陈4 小时前
面试经验分享 | 北京渗透测试岗位
运维·服务器·经验分享·安全·web安全·面试·职场和发展
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
真的很上进10 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
测试老哥11 小时前
外包干了两年,技术退步明显。。。。
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展
ThisIsClark13 小时前
【后端面试总结】深入解析进程和线程的区别
java·jvm·面试
噢,我明白了14 小时前
同源策略:为什么XMLHttpRequest不能跨域请求资源?
javascript·跨域