从本身内部引用javascript函数

考虑这段代码

var crazy = function() { console.log(this); console.log(this.isCrazy); // wrong. } crazy.isCrazy = 'totally'; crazy(); // ouput => // DOMWindow // undefined 

从疯狂()里面'这个'是指这个窗口,我猜是有道理的,因为通常你会想要这个引用函数附加到的对象,但是我怎样才能让函数引用自己,并且访问一个属性本身?

回答:

不要使用arguments.callee,只是使用一个命名函数。

“注意:你应该避免使用arguments.callee()并且给每个函数(expression式)一个名字。” 通过arguments.callee上的MDN文章

我想你是在争论争论,但是现在已经废弃了。

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee

 var crazy = function() { console.log(this); console.log(arguments.callee.isCrazy); // right. } crazy.isCrazy = 'totally'; crazy(); // ouput => // DOMWindow // totally 

正如rfw所说,如果这个函数有一个单一的名字,这是最直接的方法:

 var crazy = function() { console.log(crazy); console.log(crazy.isCrazy); }; crazy.isCrazy = 'totally'; crazy(); 

如果它可能有不同的名字,或者你想传递它,它必须包裹在一个闭包中:

 var crazy = (function(){ var that = function() { console.log(that); console.log(that.isCrazy); }; return that; })(); crazy.isCrazy = 'totally'; crazy(); 

你必须给它自己的名字,所以:

 var crazy = function() { console.log(crazy); console.log(crazy.isCrazy); } crazy.isCrazy = 'totally'; crazy(); 

这个variables只适用于一个对象的范围,例如,如果你用crazy.call(crazy)调用你的crazy函数的版本,它会调用crazy.call(crazy)函数的上下文中的函数,一切都会很好。

您可以使用call方法

 var crazy = function() { console.log(this); console.log(this.isCrazy); } crazy.isCrazy = 'totally'; crazy.call(crazy); // calls crazy using crazy as the target, instead of window: // functionToCall.call(objectToUseForThis); 

虽然如果你的函数只有一个名字,你可以这样做:

 var crazy = function() { console.log(crazy); console.log(crazy.isCrazy); } crazy.isCrazy = 'totally'; crazy(); 

我怎样才能得到函数来引用自己?

“本身”的概念并不存在于function中。 你需要的是一个对象而不仅仅是一个函数。 一个对象通过关键字“this”可以获得自己的知识。 在一个函数内,“this”指向全局对象 – 在这种情况下是窗口对象。 但是如果你使用你的函数作为构造函数来创build一个对象(使用new操作符),那么对象的this指针将指向对象本身。

即如果你写的话, 指向对象:

 var anObject = new crazy(); 

所以你可以重新编写你的代码如下:

 var crazy = function() { this.printMe = function(){ console.log(this); console.log(this.isCrazy); } } var anObject = new crazy(); //create an object anObject.isCrazy = 'totally'; //add a new property to the object anObject.printMe(); //now print 

如果您希望创build对象之前添加属性,则必须按如下方式将该属性添加到该函数的原型中:

 var crazy = function() { console.log(this); console.log(this.isCrazy); } crazy.prototype.isCrazy = 'totally'; //add the property to the function's prototype var anObject = new crazy(); //invoke the constructor 

有关代码示例的详细说明,请参阅我的博客 。

将函数绑定到自己(从@ArunPJohny和@BudgieInWA的答案中提示):

 crazy = crazy.bind(crazy); 

这会让你通过this函数访问它的属性。

 > crazy() function () { console.log(this); console.log(this.isCrazy); // works now } 

这似乎是一个比接受的答案更好的解决scheme,它使用callee弃用的callee函数,并且不能在严格模式下工作。

你现在也可以用this()recursion地调用自己的函数,如果你这么倾向的话。

我们会称之为自我提升 。 写一点实用function:

 function selfthisify(fn) { return fn.bind(fn); } crazy = selfthisify(crazy); crazy(); 

或者,如果您更喜欢更多的“语义”名称,则可以将其accessOwnProps

如果你是一个语法糖types的人,你可以添加一个selfthisify属性的函数原型:

 Object.defineProperty(Function.prototype, 'selfthisify', { get: function() { return this.bind(this); } }); 

现在你可以说

 crazy.selfthisify(); 

最简单的方法,使其本身可用的function是做var crazy = function crazy2() { crazy2(); } var crazy = function crazy2() { crazy2(); } ,疯狂的和疯狂的2可以拥有相同的名字,因为第一次出现的是外部作用域中的名字,第二个是函数体中的名字。

或干脆做function crazy() { crazy(); } function crazy() { crazy(); }这将在两个范围内定义疯狂。

你真的想创build一个对象“类”?

 function crazy(crazyState) { this.isCrazy = crazyState; console.log(this); console.log(this.isCrazy); } crazy.prototype.alertMe = function() { alert('I am '+ this.isCrazy +' crazy.'); } var crazyObj = new crazy('totally'); crazyObj.alertMe(); crazyObj.isCrazy = 'not'; crazyObj.alertMe(); 

有趣的是,你应该问,伙计。 我刚刚通过这个相同的问题来达到不同的目的 。 最终代码的快速版本是:

 $a = function() {}; $ = function() { if (!(this instanceof $)) { return new $(); } this.name = "levi"; return this; }; //helper function var log = function(message) { document.write((message ? message : '') + "<br/>"); }; log("$().name == window.name: " + ($().name == window.name)); //false log("$().name: " + $().name); //levi log("window.name: " + window.name); //result log(); log("$a instanceof $: " + ($a instanceof $)); //false log("typeof $a: " + (typeof $a)); //function log("typeof $: " + (typeof $)); //function 

关键部分:

  if (!(this instanceof $)) { return new $(); } 

如果this不是指向正确types的对象,那么它将创build一个new的对象,这将适当地确定this范围。 其余的代码就在那里进行validation,它确实按照预期工作。