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

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

问题描述

我已经做了很多搜索和一些游戏,我很确定这个问题的答案是没有,但我希望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函数可以被多个属性引用,即使在完全不同的对象上也是如此,所以没有这样的东西包含该函数的对象或属性。但是当你实际上调用一个函数时,你必须通过一个对象(至少是窗口对象来完成全局函数)调用)和该对象的属性。

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.)

我的问题是,有没有办法获得该属性名称用来调用函数,从里面函数体?我不想将属性名称作为参数传递,或者在封闭范围内的变量周围传递,或者将名称存储为保存函数引用的对象的单独属性,并使函数访问该属性的属性这个对象。

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).

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

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规范称它们为环境记录 (10.2.1),但更常见的术语是范围链
在浏览器中,全局范围是(经常窗口对象,但所有其他范围都是不是对象。
可能是用于调用函数的对象,当您调用函数时,必须位于范围内
他们是不同的。

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. They are different.

还有很多名字。


  • 调用函数时,需要引用,例如通过对象属性。此参考可能具有名称。

  • 范围链具有声明始终具有名称。

  • A 功能(真正的功能,不是参考)可能也有一个功能名称 - 你的 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 has 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)

所以,a函数引用可能来自绑定(例如函数声明),对象(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函数,它引用一个新的全局范围的结果(在< a href =https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode =nofollow noreferrer>严格模式,无论如何),它引用了一个函数调用statement,引用一个组,它引用一个匿名的Function对象,它包含表达并返回一个名为'a'的函数的代码。

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的属性名称,它应该得到哪一个? EVAL? 功能? 匿名? 一个?他们都是?
在回答之前,请考虑一些复杂问题,例如跨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天全站免登陆