gpt4 book ai didi

javascript - 你能得到调用函数的属性名吗?

转载 作者:行者123 更新时间:2023-11-30 07:08:31 25 4
gpt4 key购买 nike

我已经进行了大量的搜索和一些尝试,我很确定这个问题的答案是,但我希望 JavaScript 专家可能有窍门他的袖子可以做到这一点。

一个 JavaScript 函数可以被多个属性引用,甚至是在完全不同的对象上,所以没有对象或属性这样的东西来保存函数。但是任何时候你实际调用一个函数,你必须通过一个单一的对象(至少,用于全局函数调用的window对象)和它的属性来完成对象。

(函数也可以通过函数局部变量调用,但我们可以将函数局部变量视为作用域激活对象的属性,因此这种情况也不异常(exception)。)

我的问题是,有没有办法从函数体内部获取用于调用函数的属性名称?我不想将属性名称作为参数传入,或者在封闭范围内关闭变量,或者将名称作为单独的属性存储在包含函数引用的对象上,并让函数访问该名称属性this 对象。

这是我想做的一个例子:

var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };

callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'

根据我的搜索,看起来与上面最接近的是 arguments.callee.name,但这行不通,因为它只返回固定到定义时的函数对象,并且仅当它被定义为命名函数时(我的示例中的函数不是)。

我还考虑过,也许您可​​以遍历 this 对象的所有属性,并测试与 arguments.callee 是否相等,以找到其值为对的引用的属性函数本身,但这也不起作用(在一般情况下),因为在对象自己的(或继承的)属性集中可能有多个对该函数的引用,如我的示例所示。 (另外,这似乎是一种低效的解决方案。)

这可以做到吗?

最佳答案

简答:

  1. 不,您无法获取用于调用您的函数的“属性名称”。
  2. 可能根本没有名称,或者在不同范围内有多个名称,因此“属性名称”的定义很不明确。
  3. arguments.callee 已弃用,不应使用。
  4. 不存在不使用参数或闭包的解决方案。

长答案:

正如 thefourtheye 评论的那样,您应该重新考虑您正在尝试做的事情,而不是在一个新问题中提出这个问题。但是有一些常见的误解,所以我会尝试解释为什么你不能得到“简单的属性名”。

原因不简单。

在我们继续之前,让我们澄清一些事情。 激活对象根本不是对象。ECMAScript 5.1 规范称它们为 Environment Records (10.2.1) ,但更常见的术语是 Scope chain。在浏览器中,全局范围是 ( often ) window 对象,但所有其他范围不是 对象。可能有一个您用来调用函数的对象,当您调用函数时,您必须在某个范围中。

除了少数异常(exception),范围不是对象,对象也不是范围。

然后,有很多名字。

  • 当您调用一个函数时,您需要引用它,例如通过一个对象属性。此引用可能有一个名称。
  • 作用域链有声明总是有一个名字。
  • 一个 Function(真正的函数,不是引用)可能也有一个函数名称 - 你的 arguments.callee.name - 这是固定在声明中。

它们不仅名称不同,而且(总是)不是您要查找的“属性名称”。

var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)

因此,函数引用可能来自绑定(bind)(例如函数声明)、对象(arguments.callee)或变量。它们都是References (8.7) .引用确实有一个名字(可以这么说)。

要注意的是,函数引用并不总是来自对象或作用域链,而且它的名称并不总是被定义。例如一个常见的闭包技术:

(function(i){ /* what is my name? */ })(i)

即使引用确实有名称,函数调用 (11.2.3)不会以任何方式将引用或其名称传递给函数。这让 JavaScript 引擎保持理智。考虑这个例子:

eval("(new Function('return function a(){}'))()")() // Calls function 'a'.

最后的函数调用引用了 eval 函数,它引用了一个新的全局作用域的结果(无论如何在 strict mode 中),它引用了一个函数调用语句,它引用了一个组,它引用了一个匿名函数对象,并且其中包含表达并返回名为“a”的函数的代码。

如果要从a中获取“属性名称”,应该获取哪个? “评估”? “功能”? “匿名的”? “A”?他们全部?在你回答之前,考虑复杂的情况,例如跨 iframe 的函数访问,它具有不同的全局变量和跨源限制,或者与 native 函数的交互(例如 Function.prototype.bind),你会看到它如何迅速变成 hell 。

这也是为什么 arguments.caller__caller__ 和其他类似技术现在都被弃用的原因。一个函数的“属性名”定义得比调用者还要糟糕,几乎不切实际。至少调用者始终是执行上下文(不一定是函数)。

因此,不知道您真正的问题是什么,获得“属性名称”的最佳选择是使用闭包。

关于javascript - 你能得到调用函数的属性名吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28260389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com