从内部引用javascript函数

时间:2011-05-22 04:20:31

标签: javascript

考虑这段代码

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

从内部疯狂()'这个'指的是窗口,我觉得这很有意义,因为通常你想要这个引用函数附加的对象,但是我怎样才能让函数引用它自己,并访问自己设置的属性?

答案:

不要使用arguments.callee,只需使用命名函数。

“注意:你应该避免使用arguments.callee(),只需给每个函数(表达式)一个名字。”通过MDN article on arguments.callee

12 个答案:

答案 0 :(得分:26)

我认为你要求arguments.callee,但现在已弃用

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

答案 1 :(得分:14)

正如 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();

答案 2 :(得分:4)

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

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

变量this仅适用于对象的范围,例如,如果您使用crazy调用crazy.call(crazy)函数的版本,它将调用该函数函数crazy的上下文,一切都会很好。

答案 3 :(得分:4)

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

crazy = crazy.bind(crazy);

这将允许您通过this从函数访问其属性。

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

这似乎是一个比接受的答案更好的解决方案,它使用了callee功能,该功能已弃用且不能在严格模式下运行。

您现在也可以使用this()以递归方式调用函数,如此倾向。

我们称之为自我暗示。写一点实用功能:

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

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

如果你是一个语法糖类型的人,你可以在Function原型中添加一个selfthisify属性:

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

现在你可以说

crazy.selfthisify();

答案 4 :(得分:3)

这必须处理函数crazy的范围。如果可以使用函数call()将任何范围传递给函数。

而不是

crazy();

使用

crazy.call(crazy);

详情请参阅 http://odetocode.com/blogs/scott/archive/2007/07/05/function-apply-and-function-call-in-javascript.aspx {
{3}} {
{3}}

答案 5 :(得分:2)

您可以使用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();

答案 6 :(得分:2)

  

如何获取要引用的功能   本身?

“本身”的概念与功能不存在。你需要的是一个对象而不仅仅是一个函数。对象通过关键字“this”可以了解自身。在一个函数中,'this'指向全局对象 - 在本例中是window对象。但是如果你使用你的函数作为构造函数来创建一个对象(使用 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

如果您希望在之前添加属性,则必须将该属性添加到函数的 prototype 中,如下所示:

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

有关代码示例的详细说明,请参阅my blog的更多信息。

答案 7 :(得分:1)

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

或者只是做function crazy() { crazy(); },这将在两个范围内定义疯狂。

答案 8 :(得分:0)

你真的想创建一个对象'class'吗?

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();

答案 9 :(得分:0)

有趣的是你应该问,伙计。我刚刚完成了this same issue for a different purpose。最终代码的快速版本是:

$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没有指向正确类型的对象,那么它会生成一个new,这将正确定位this。其余的代码只是用于验证它确实按预期工作。

答案 10 :(得分:0)

为了让您的代码可以运行,请按照以下

进行操作

&#13;
&#13;
        function crazy_object (crazy) {
          this.isCrazy = crazy
        }
        
        var create_crazy = new crazy_object('hello') //creating object
        
        console.log(create_crazy); //=> { isCrazy = 'hello' }
        
        var crazy = function() {
            console.log(this); //=> { isCrazy = 'totally' }
            console.log(this.isCrazy); //=> 'totally'
        }
        
        create_crazy.isCrazy = 'totally'; //=> isCrazy = 'totally'
        //below we pass the created object in function crazy.
        //And doing that we can use the keywork `this` and refer to the object
        crazy.call(create_crazy, null);
&#13;
&#13;
&#13;

  

使用callapply方法,我们可以传递给函数a   属性,在该函数中,我们可以使用带有关键字this

的属性

例如:

&#13;
&#13;
function speak (message) {
  console.log(`A person with name ${this.name} say ${message}`);
}

speak.call({ name: 'Roland' }, 'Javascript is awesome');
&#13;
&#13;
&#13;

与财产一起使用:

function speak (message) {
  console.log(`A person with name ${this.name} say ${message}`);
}

var name = 'Roland'

speak.call({ name }, 'Javascript is awesome');

答案 11 :(得分:0)

我个人认为,由于关键字“ this”,在函数内部使用函数的正确方法是在构造函数内部使用构造函数:

    this;

定义函数并在自身内部重用它们使开发人员无法控制范围。在现实的用例中,即使一切看起来好像在自身内部调用的函数似乎都正常运行,在h * ll中也无法将其放入生产代码中。通过使用'this'关键字创建对象并将参数值分配给变量,如下所示:

    new SumObj{
      constructor(delta, epsilon, zeta){
          this.delta = delta;
          this.epsilon = epsilon;
          this.zeta = zeta;
      }
    }

您实际上是在控制具有相同名称的变量的不同层的范围。在这种情况下,不控制变量的范围很可能引起开发人员的痛苦。

    new SumObj('someStr', 300, true);

以这种方式使用对象将创建一个具有其自身唯一作用域的新实例;这使您可以信任变量的值,并且不会得到意外的结果。

  • Bellow是一种非常简单的用法,实际上在现实世界中的应用中很实用。测试正在处理的Node.JS项目时,我使用与此类似的对象进行打印。

class PrintObj {
    constructor(obj) {
        this.vals = Object.values(obj);
        this.keys = Object.keys(obj);

        for(let i = 0; i < this.vals.length; i++) {
            const el = this.vals[i];

            if(typeof el === 'object'){ 
                new PrintObj(el);
            } else {
                console.log(`\t ${this.keys[i]} : ` + el);
            }
        }
    }
}

const sumObj = {
    alpha: 'Hello World!',
    beta: 'Hello From Universe!',
    gamma: 'Hello Developers!',
    delta: {
        a: '0',
        b: '1',
        c: '2',
        e: '3',
        f: '4',
    },
    epsilon : 'Hello Mum',
    zeta : 'Hello Papa'
};
new PrintObj(sumObj);