你能得到调用函数的属性名吗? [英] Can you get the property name through which a function was called?

查看:23
本文介绍了你能得到调用函数的属性名吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经做了很多搜索和一些尝试,我很确定这个问题的答案是,但我希望 JavaScript 专家可能有技巧他的袖子可以做到这一点.

I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.

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

A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.

(函数也可以通过函数局部变量来调用,但是我们可以把函数局部变量看作作用域的激活对象的一个​​属性,所以这种情况也不例外.)

(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)

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

My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.

这是我想做的一个例子:

Here's an example of what I want to do:

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,但这不起作用,因为它只返回固定到定义时的函数对象,并且仅当它被定义为命名函数(我的示例中的函数不是).

From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).

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

I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)

这能做到吗?

推荐答案

简短回答:

  1. 不,您无法获得用于调用您的函数的属性名称".
  2. 可能根本没有名称,或者在不同范围内有多个名称,因此属性名称"的定义很不明确.
  3. arguments.callee 已弃用,不应使用.
  4. 不存在不使用参数或闭包的解决方案.
  1. No, you cannot get "the property name" used to call your function.
  2. There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
  3. arguments.callee is deprecated and should not be used.
  4. There exists no solution that does not use arguments or closure.

长答案:

正如 thefourtheye 评论的那样,您应该重新思考您要尝试做什么,并在一个新问题中提出这个问题.但是有一些常见的误解,所以我会试着解释为什么你不能得到简单的属性名称".

As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".

原因是因为它不简单.

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

Before we go ahead, let us clarify something. Activation Objects are not objects at all. The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain. In a browser the global scope is (often) the window object, but all other scopes are not objects. There may be an object that you use to call a function, and when you call a function you must be in some scope.

除了少数例外,范围不是对象,对象也不是范围.

With few exceptions, scopes are not objects, and objects are not scopes.

然后,有很多名字.

  • 当你调用一个函数时,你需要引用它,比如通过一个对象属性.这个参考可能有一个名字.
  • 作用域链有声明总是有一个名字.
  • 一个Function(真正的函数,不是引用)可能也有一个函数名——你的arguments.callee.name——它是固定在声明.
  • When you call a function, you need to reference it, such as through an object property. This reference may have a name.
  • Scope chain has declarations, which always have a name.
  • A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.

它们不仅名称不同,而且(始终)不是您要寻找的属性名称".

Not only are they different names, they are not (always) the "the property name" you are seeking.

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)

因此,函数引用可能来自binding(例如函数声明)、Object(arguments.callee)或变量.它们都是参考资料 (8.7).并且参考确实有一个名字(可以这么说).

So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable. They are all References (8.7). And reference does have a name (so to speak).

问题在于,函数引用并不总是来自对象或作用域链,其名称也并不总是被定义.例如一个常见的关闭技术:

The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined. For example a common closure technique:

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

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

Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way. Which keeps the JavaScript engine sane. Consider this example:

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

最后的函数调用引用了 eval 函数,它引用了新的全局作用域的结果(在 严格模式,无论如何),它指的是一个函数调用语句,它指的是一个组,它指的是一个匿名的Function对象,其中包含表达和返回一个名为'的函数的代码一个'.

The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.

如果您想从 a 中获取属性名称",应该获取哪个?评估"?功能"?匿名的"?一个"?他们都是?在回答之前,请考虑复杂性,例如跨 iframe 的函数访问,它具有不同的全局变量和跨源限制,或与本机函数的交互(例如 Function.prototype.bind),您将看到它是如何迅速变成地狱的.

If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them? Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.

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

This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated. The "property name" of a function is even more ill defined than the caller, almost unrealistic. At least caller is always an execution context (not necessary a function).

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

So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.

这篇关于你能得到调用函数的属性名吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆