这个指针来自内部函数

Ant*_*nAL 5 javascript scope

我有JavaScript组件,具有以下架构:

var MyComponent = function(params)
{
    setup(params);


    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup

        // Interaction logic
        var _this = this; // "this" points to DOMWindow, not to created object
        $(".some-element").click(function(){
            _this.doSomething(); // it craches here, because of above
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

当由交互逻辑控制的事情发生时,有时我必须将执行转发到组件的"公共"方法.

在这种情况下,我有"这个"指针的问题.

示例代码演示了它:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal();
    };
    function _sayInternal()
    {
        this.say();
    };
};
Run Code Online (Sandbox Code Playgroud)

要测试它,

  • 创建一个对象:

var o = new Item();

  • 这很好用:

o.say(); // alerts "hello"

  • 这崩溃了:

o.sayInternal();

我收到一个错误:

TypeError:表达式'this.say'[undefined]的结果不是函数.

我认为,这样的行为发生,因为_sayInternal()函数声明(而不是分配给对象,如"this.say =功能()").这样,它在所有创建的对象之间共享,并且像C++中的静态函数一样.

这是真的 ?

Fel*_*ing 3

不,sayInternal不在创建的对象之间共享。但你是对的,创建的对象无权访问,sayInternal因为它没有分配给它们。该函数仅是构造函数的局部函数。

this总是指调用函数的上下文。如果您像这样调用它func(),那么this指的是全局对象(位于window浏览器中)。如果将函数设置为对象的属性并使用 调用它obj.func(),则将this引用obj

如果将“绑定”函数分配给变量并调用它:

var method = obj.func;
method();
Run Code Online (Sandbox Code Playgroud)

然后this会再次引用全局对象。在 JavaScript 中,函数就像任何其他值一样,它们与分配给它们的对象没有特殊关系。


call您可以使用或显式设置上下文apply

var MyComponent = function(params)
{
    setup.call(this, params); // <- using `call`

    this.doSomething()
    {
        // doing something
    };

    function setup(params)
    {
        // Setup  
        // Interaction logic
        var _this = this; // "this" to new  created object
        $(".some-element").click(function(){
            _this.doSomething();
        });
    }
};
Run Code Online (Sandbox Code Playgroud)

或者在你的其他例子中:

var Item = function()
{
    this.say = function()
    {
        alert("hello");
    };
    this.sayInternal = function()
    {
        _sayInternal.call(this);
    };
    function _sayInternal()
    {
        this.say();
    };
};
Run Code Online (Sandbox Code Playgroud)

也就是说,这种将函数分配给对象的方法并不好,因为每个实例都有自己的 this.sayInternal函数。所以对于Item上面的代码,每次创建实例都涉及创建三个函数,这很浪费内存。

利用原型继承将是一个更好的方法:

var Item = function() {
};

Item.prototype = (function() {
    function _sayInternal() {
        this.say();
    };

    return {
        say: function() {
            alert("hello");
        },
        sayInternal: function(){
            _sayInternal.call(this);
        }
    }
}());
Run Code Online (Sandbox Code Playgroud)

这样,_sayInternal只创建一次,所有实例都继承(引用)原型,因此saysayInternal也只存在一次。带有立即函数的“技巧”使得_sayInternal只能通过say和访问sayInternal