当前位置: 首页 > 知识库问答 >
问题:

ES6中常规函数中的“this”与胖箭头函数,以猫鼬为例进行说明

蒙华翰
2023-03-14

路由器/用户.js路由:

router.post('/register', auth.optional, (req, res, next) => {
  const {
    body: { user }
  } = req

  // validation code skipped for brevity

  const finalUser = new User(user)
  finalUser.setPassword(user.password)

  // to save the user in Mongo DB
  return finalUser.save().then(() => res.json({ user: finalUser.toAuthJSON() }))
})

发送的Post请求的正文为:

{
    "user":{
        "email":"leon@idiot.com",
        "password": "123abc"
    }
}

在数据库模式的< code>model/User.js中:

const UserSchema = new Schema({
  email: String,
  hash: String,
  salt: String
})


// Please note: this is a regular/normal function definition
UserSchema.methods.setPassword = function (password) {
  // this references the UserSchema created
  this.salt = crypto.randomBytes(16).toString('hex')
  console.log(`salt: ${this.salt}`)
  this.hash = crypto
    .pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
    .toString('hex')
  console.log(`hash: ${this.hash}`)
}

现在一切正常。日志输出为:

salt: e7e3151de63fc8a90e3621de4db0f72e
hash: 19dd9fdbc78d0baf20513b3086976208ab0f9eee6d68f3c71c72cd123a06459653c24c11148db03772606c40ba4846e2f9c6d4f1014d329f01d22805fc988f6164fc13d4157394b118d921b9cbd742ab510e4d2fd4ed214a0d523262ae2b2f80f6344fbd948e8c858f95ed9706952db90d415312156a994c65c42921afc8c3e5b1b24a923219445eec8ed62de313ab3d78dc93b715689a552b6449870c5bfcc3bec80c4438b1895cab41f92ef681344ac8578de476a82aa798730cf3a6ef86973a4364a8712c6b3d53ce67ffffd7569b9ade5db09ad95490354c6f7194fdd9d8f8a1cb7ccddf59e701198a1beee59a2dd6afb90ae50e26ea480e9a6d607e4b37857a02016ee4d692d468dd9a67499547eb03fc6cfa676686f7990c2251c9516459288c55584138aed56a5df6c4692f7ef6925e8f3d6f6a0c780c4d80580447f2b1258bea799a8c7eb9da878ab70a94c4227ec03d18d56b2722c315d0e2b2681d81d78d4213288f7305cbbfa377c3b2eb75e0f0b093e6067b14adce4a01f0a7bde8515350a1c987739c12574ec4c49008510e2e7e5534f9b76d15b1af68e43ef54e6b8a1bea859aafd23d6b6bc61d5b1965004cd6dd933545cf755f3e6dfc8f230f37a79a8bc006b9b14465b1b08d60cb45ef3b6a1b73f5afac90bdc58d5ec15c7596dc7e8d503f8dfbd6a3289cf997da2031389c7f3d165e34b29178f3daf76d
3

但它不适用于这样的定义:

UserSchema.methods.setPassword = password => {
  // what this reference is undefined, so are ones below
  this.salt = crypto.randomBytes(16).toString('hex')
  console.log(`salt: ${this.salt}`)
  this.hash = crypto
    .pbkdf2Sync(password, this.salt, 10000, 512, 'sha512')
    .toString('hex')
  console.log(`hash: ${this.hash}`)
}

错误是:

{
    "errors": {
        "message": "Cannot set property 'salt' of undefined",
        "error": {}
    }
}

这意味着该引用的未定义

我在网上发现,胖箭头函数明确禁止绑定this,这是一个范围问题,在胖箭头函数中,这个
this具有其直接对象的范围。但我不能说我理解得很好
1.在这种情况下,胖箭头函数中this的范围是什么
2.在正常函数定义中,这个的范围是什么
3.在这种情况下,如何访问对象:UserSchema,胖箭头函数中的属性(请原谅我使用了不太合适的单词)与普通函数定义中的属性一样?

这些帖子很有帮助:< br >‘箭头函数’和‘函数’是等价的/可交换的吗?< br>“this”关键字是如何工作的?< br >

但在弄清楚我的具体问题之前,我仍然希望在特定情况下得到答案。

共有1个答案

江向阳
2023-03-14

你误解的核心是:

fat-arrow函数中的this具有立即对象的范围

不对。它的上下文在当前执行的功能/环境的范围内被解析。

例子:

// global scope outside of any function:

let foo = {};

// Define a method in global scope (outside of any function)
foo.a = () => {
    console.log(this); // undefined
}

// Return a function from scope of a method:
foo.b = function () {
    // remember, "this" in here is "foo"

    return () => {
        console.log(this); // foo - because we are in scope foo.c()
    }
}

foo.a();   // undefined
foo.b()(); // foo

对于箭头函数,重要的不是函数属于什么对象,而是它被定义在哪里。在第二个例子中,函数可以完全不属于foo,但仍然会打印foo,不管怎样:

bar = {};
bar.b = foo.b();

bar.b(); // will log "foo" instead of "bar"

这与常规函数相反,常规函数取决于您如何调用它们,而不是您定义它们的位置:

// Defined in global scope:
function c () {
    console.log(this);
}

bar.c = c;
bar.c(); // will log "bar" instead of undefined because of how you call it

注意,这里有两个非常不同的概念混合在一起——上下文(这个“值”是什么)和范围(函数中哪些变量是可见的)。箭头函数使用范围来解析上下文。常规函数不使用作用域,而是取决于如何调用它们。

现在回答你的一些问题:

  1. 在这种情况下,这个在胖箭头函数中的作用域是什么?

正如我所说。范围和这是两个不相关的概念。这背后的概念是对象/实例上下文,也就是说,当一个方法被调用时,作用于哪个对象的方法是什么。范围的概念很简单,比如什么是全局变量,什么变量只存在于特定函数中,它可以演变成更复杂的概念,比如闭包。

因此,由于作用域始终相同,唯一的区别在于箭头函数,其上下文(其 this)由作用域定义。也就是说,当声明函数时,它在哪里声明?在文件的根目录下?然后它具有全局范围,这等于“未定义”。在另一个函数中?然后,这取决于如何调用该函数。如果它被调用为一个对象的方法,例如如果用户化学方法.生成密码塞特()返回一个箭头函数,那么该函数(我们称之为setPassword())将具有正确的对象。

根据我上面的解释,我只能说作用域不涉及正常函数中< code>this的值。有关< code>this如何工作的更详细解释,请参见我对另一个问题的回答:Javascript中的“this”关键字如何在对象文字中起作用?

它的定义方式是不可能的。您需要从一个常规函数中定义它,该函数具有以下指向用户舍马

UserSchema.methods.generatePasswordSetter = function () {
    return (password) => { /* implementation... */}
}

但这可能不是你想要的。在这种情况下,要做你想做的事情,你只需要停止使用箭头函数。对于像这样的用例,常规函数仍然存在。

 类似资料:
  • 问题内容: class App extends Component { constructor(props) { … } 在类中声明的两种函数 (onChange和onSubmit) 之间有什么区别?如果我将其声明为ES6类方法,但在 const url中 引用this.sate时出现错误,但是将其更改为arrow函数可以解决此问题。 我想知道两种情况下如何正确处理“ this” 另外,我该如何做

  • 本文向大家介绍JavaScript中的常规函数​​与箭头函数?,包括了JavaScript中的常规函数​​与箭头函数?的使用技巧和注意事项,需要的朋友参考一下 常规函数与箭头函数 一个箭头函数来简洁编写代码。常规 函数和箭头 函数的工作方式相似,但是它们之间存在一些差异。让我们简要地讨论一下这些差异。 箭头函数的语法 正则函数的语法 “ this”关键字的用法 它不能在箭头功能中使用“ this”

  • 问题内容: 我是React的新手,正在尝试了解语法。 我正在React 15环境中进行开发(使用react-starterify模板),并且一直在使用下面的VERSION 2中的语法,但是,我在Facebook的React页面上发现的大多数示例和教程都是VERSION 1。这两个,何时应在另一个之上使用? 版本1 版本2 问题答案: 第二个代码是 无状态功能组件, 并且是用于将组件定义为的函数的新

  • 新的“胖箭头”符号还可以用更简单的方式来定义匿名函数。 请看下面的例子: console.log(x); incrementedItems.push(x+1); }); 计算一个表达式并返回值的函数可以被定义更简单: 下面代码与上面几乎等价: incrementedItems = items.map(function (x) { return x+1; 让我们在 验

  • 本文向大家介绍箭头函数中this指向举例?相关面试题,主要包含被问及箭头函数中this指向举例?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: //输出22 定义时绑定。

  • 本文向大家介绍ES6中的箭头函数实例详解,包括了ES6中的箭头函数实例详解的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了ES6中的箭头函数。分享给大家供大家参考,具体如下: 语法 我们先来看看箭头函数的语法: param 是参数,根据参数个数不同,分这几种情况: 示例 我们再来看看一些示例,看看在ES5中的函数怎么通过ES6中的箭头函数来替代吧: 当然,也可以定义多个参数: 当然=>后面