我已经进行了很多搜索,并且还玩得很开心,而且我很确定这个问题的答案是否定的,但是我希望JavaScript专家可能会花一些时间来做到这一点。
一个JavaScript函数可以被多个属性引用,即使在完全不同的对象上也是如此,因此不存在持有该函数的对象或属性。但是,每次实际调用函数时,都必须通过单个对象(至少是window
用于全局函数调用的对象)和该对象的属性来实现。
(也可以通过函数局部变量来调用函数,但是我们可以将函数局部变量视为作用域的激活对象的属性,因此该情况也不是该规则的例外。)
我的问题是,有没有办法让被用来调用的函数,从属性名内部函数体?我不想将属性名称作为参数传递,也不想在封闭范围内的变量周围传递闭包,也不想将名称作为单独的属性存储在持有函数引用并让函数访问该名称属性的对象上的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
,但这是行不通的,因为它仅返回在定义函数对象时固定在函数对象上的名称,并且仅在将其定义为a时才返回。命名函数(在我的示例中不是)。
我还认为,也许您可以遍历this
对象的所有属性并测试是否相等,arguments.callee
以找到其值是对函数本身的引用的属性,但是(在一般情况下)也不起作用,因为有可能在我自己的示例中,是对象自身(或继承)属性集中对该函数的多个引用。(此外,这似乎是一种低效的解决方案。)
能做到吗?
简短答案:
arguments.callee
已弃用,不应使用。长答案:
正如thefourtheye所评论的那样,您应该重新考虑您要做什么,并在一个新问题中提出这个问题。但是,存在一些常见的误解,因此,我将尝试解释为什么您无法获得“简单属性名称”。
原因是因为它并不简单。
在继续之前,让我们澄清一些事情。激活对象根本不是对象。ECMAScript 5.1规范将其称为Environment Records
(10.2.1),但更通用的术语是Scope chain
。在浏览器在全球范围(通常)的window
对象,但所有其他范围都没有对象。有可能是你用来调用函数的对象,当你调用一个函数,你必须在一定范围内。
除少数例外,范围不是对象,并且对象不是范围。
然后,有很多名字。
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)
因此,函数引用可能来自binding
(例如,函数声明),Object
(arguments.callee)或variable
。它们都是References
(8.7)。并且引用确实有一个名字(可以这么说)。
问题是,函数引用并不总是来自对象或作用域链,并且其名称也不一定总是定义的。例如,一种常见的关闭技术:
(function(i){ /* what is my name? */ })(i)
即使引用确实具有名称,函数调用(11.2.3)也不会以任何方式将引用或其名称传递给函数。这使JavaScript引擎保持理智。考虑以下示例:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
最终的函数调用引用eval函数,该引用引用新的全局范围的结果(无论如何在严格模式下),引用一个函数调用语句,引用一个组,引用一个匿名的Function对象,并且包含包含以下代码的代码:表示并返回一个称为“ a”的函数。
如果要从一个内部获取“属性名称”,应该获取哪个名称?“评估”?“功能”?“匿名的”?“一种”?他们都是?在回答之前,请考虑一下复杂性,例如跨iframe的函数访问(具有不同的全局变量以及跨原点限制),或者与本机函数的交互(Function.prototype.bind
例如),您将看到它如何迅速变成地狱。
这也是为什么arguments.caller
,__caller__
以及其他类似的技术,现在都过时了。函数的“属性名称”比调用者定义得更糟,几乎是不现实的。至少调用者始终是执行上下文(不一定是函数)。
因此,不知道您的真正问题是什么,获得“属性名称”的最佳选择是使用闭包。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句